关于char,unsigned char,unsigned short之间的关系的一道题

pengfoo 2012-02-28 03:14:25

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char cA;
unsigned char ucB;
unsigned short usC;

cA=128;
ucB=128;

usC=cA+ucB;
printf("%d\n",usC);//1

usC=cA+(short)ucB;
printf("%d\n",usC);//2

usC=(unsigned char)cA+ucB;
printf("%d\n",usC);//3

usC=cA+(char)ucB;
printf("%d\n",usC);//4

getchar();
return EXIT_SUCCESS;
}



输出是:
0
0
256
65280
搞了半天也没搞懂。大家分析分析啊!
...全文
805 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
wenhai_zh 2012-11-03
  • 打赏
  • 举报
回复
引用 3 楼 nice_cxf 的回复:
引用 1 楼 eternalxlm 的回复:Char 是-128~127,cA=128; 128=0x80;0x80看作有符号数其实就是-128 前3个就好理解了 第4个ucB=128=0x80,转成有符号的就是-128加上cA就是-256再转成us就是65536-256=65280 第四个结论对了但过程不对 先都转成了unsigned short,ca = -1……
三楼的分析是正确的。里面涉及到整形提升,还有溢出的问题。对于这个细节问题大家都没有耐心的解释。我这个参考了一篇文章,里面讲解的很清楚。http://blog.csdn.net/gukesdo/article/details/6909766。还有就是三楼有个明显的纰漏,就是最后的结果应该是0XFF00=65280.
eternalxlm 2012-02-29
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 kuzuozhou 的回复:]
usC=cA+(char)ucB;
为什么是cA转成unsigned short类型,ucB转成char ,再转成unsigned short,两者相加?
而不是先是char 类型的cA和char 类型的ucB相加,然后转成unsigned short类型的usC?

引用 3 楼 nice_cxf 的回复:
引用 1 楼 eternalxlm 的回复:
Char 是-128~127,……
[/Quote]

先怎么算和系统位数有关,32位系统中,其实先转成32位的,再相加,VC6.0编译如下:
596: s=a+(char)b;
00402D7C movsx edx,byte ptr [ebp-0ACh] //movsx,带标志位的MOV,会根据原char最高位填充高字节 0x80变为0xffffff80
00402D83 movsx eax,byte ptr [ebp-0B0h]
00402D8A add edx,eax //edx=0xffffff80+0xffffff80 = 0xffffffff00
00402D8C mov word ptr [ebp-0B4h],dx //取edx的低2字节,变成0xff00,看成有符号为-256,看成无符号为=-256+65536=65280

有无符号是C语言的事情,汇编这层根本不关心,C语言编译时要自行转换为补码。2字节-256和65280存在内存或寄存器中的值完全一样,至于是正是负看实际C代码中如何定义。



pengfoo 2012-02-29
  • 打赏
  • 举报
回复
usC=cA+(char)ucB;
为什么是cA转成unsigned short类型,ucB转成char ,再转成unsigned short,两者相加?
而不是先是char 类型的cA和char 类型的ucB相加,然后转成unsigned short类型的usC?
[Quote=引用 3 楼 nice_cxf 的回复:]
引用 1 楼 eternalxlm 的回复:
Char 是-128~127,cA=128; 128=0x80;0x80看作有符号数其实就是-128
前3个就好理解了
第4个ucB=128=0x80,转成有符号的就是-128加上cA就是-256再转成us就是65536-256=65280

第四个结论对了但过程不对
先都转成了unsigned short,ca = -128转换成0xff……
[/Quote]
DNcx831 2012-02-28
  • 打赏
  • 举报
回复
22: usC=cA+(char)ucB;
004010B2 movsx eax,byte ptr [ebp-4]
004010B6 movsx ecx,byte ptr [ebp-8]
004010BA add eax,ecx
004010BC mov word ptr [ebp-0Ch],ax

编译器优化了,不好理解。理解上用一楼的就可以了。

caohaiwd 2012-02-28
  • 打赏
  • 举报
回复
下面是转化为汇编的情形,注意指令,一个是符号扩展movs,一个是零扩展movz,简单来说比如0xff,零扩展为2个字节为0x00ff,也就是说简单地补0,而符号扩展是根据最高位(符号)来补0或1,0xff(-1)符号扩展到2个字节为0xffff(-1).零扩展适合无符号类型的扩展,符合扩展适合有符号类型的扩展
movb $-128, 28(%esp) //ca
movb $-128, 29(%esp) //ucb
movsbw 28(%esp),%dx
movzbl 29(%esp), %eax
leal (%edx,%eax), %eax
movw %ax, 30(%esp)//usc
movzwl 30(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf

movsbw 28(%esp),%dx
movzbl 29(%esp), %eax
leal (%edx,%eax), %eax
movw %ax, 30(%esp)
movzwl 30(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)

call _printf
movb 28(%esp), %al
movzbl %al, %edx
movzbl 29(%esp), %eax
leal (%edx,%eax), %eax
movw %ax, 30(%esp)
movzwl 30(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf

movsbw 28(%esp),%dx
movb 29(%esp), %al
cbtw
leal (%edx,%eax), %eax
movw %ax, 30(%esp)
movzwl 30(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
nice_cxf 2012-02-28
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 eternalxlm 的回复:]
Char 是-128~127,cA=128; 128=0x80;0x80看作有符号数其实就是-128
前3个就好理解了
第4个ucB=128=0x80,转成有符号的就是-128加上cA就是-256再转成us就是65536-256=65280
[/Quote]
第四个结论对了但过程不对
先都转成了unsigned short,ca = -128转换成0xff80,ucb先转char变成-128然后同样转成0xff80
0xff80+0xff80,溢出后=0xfe00=65280
炼气士 2012-02-28
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 eternalxlm 的回复:]

Char 是-128~127,cA=128; 128=0x80;0x80看作有符号数其实就是-128
前3个就好理解了
第4个ucB=128=0x80,转成有符号的就是-128加上cA就是-256再转成us就是65536-256=65280
[/Quote]

最后一个不理解,为什么是65536-256?
eternalxlm 2012-02-28
  • 打赏
  • 举报
回复
Char 是-128~127,cA=128; 128=0x80;0x80看作有符号数其实就是-128
前3个就好理解了
第4个ucB=128=0x80,转成有符号的就是-128加上cA就是-256再转成us就是65536-256=65280

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧