在C语言中有符号数转化为无符号会出现一些问题,先看以下的程序例子:
- int
main() - {
-
char ch[12] = {0xF0, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00}; -
unsigned int result = (ch[7] << 8) + ch[6]; // ch[7]为0x0F, ch[6]为0xFF -
printf("result(0x%x), ch[7](0x%x), ch[6](0x%x)\n", result, ch[7], ch[6]); -
return 0; - }
![<wbr>有符号数与无符号数的强制类型转换问题](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
原来ch[6]在char转成unsigned int时由0xff转为了0xffffffff。它的符号位(最高位)为1,在转换成无符号数时将其他位(第9位至第32位)全置为1。所以最后的计算result的结果不0xFFF而是0xEFF。我们来看一下反汇编,就更加清楚了。
-
unsigned int result = (ch[7] << 8) + ch[6]; - 00411C68
movsx eax,byte ptr [ebp-0Dh] - 00411C6C
shl eax,8 - 00411C6F
movsx ecx,byte ptr [ebp-0Eh] - 00411C73
add eax,ecx - 00411C75
mov dword ptr [ebp-20h],eax
1. 将8位的有符号数扩展成32位的有符号数
2. 对扩展后的32位有符号数进行移位和相加操作
3. 将有符号数以无符号数的形式显示
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
我们看一下不同字节数的无符号数转换例子:
- int
main() - {
-
unsigned char ch[12] = {0xF0, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00}; -
unsigned int result = (ch[7] << 8) + ch[6]; -
printf("result(0x%x), ch[7](0x%x), ch[6](0x%x)\n", result, ch[7], ch[6]); -
return 0; - }
那为什么这里输出的结果又是正确的呢?我们来看一下反汇编的结果:
-
unsigned int result = (ch[7] << 8) + ch[6]; - 00411C68
movzx eax,byte ptr [ebp-0Dh] - 00411C6C
shl eax,8 - 00411C6F
movzx ecx,byte ptr [ebp-0Eh] - 00411C73
add eax,ecx - 00411C75
mov dword ptr [ebp-20h],eax
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
我们将第一个例子改一下,在计算result值的时候先将char类型的ch[7]和ch[6]强制转换为unsigned char看一下最后得到结果会如何。下面是修改后的代码:
- int
main() - {
-
char ch[12] = {0xF0, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00}; -
unsigned int result = (((unsigned char) ch[7]) << 8) + ((unsigned char)ch[6]); -
printf("result(0x%x), ch[7](0x%x), ch[6](0x%x)\n", result, (unsigned char)ch[7], (unsigned char)ch[6]); -
return 0; - }
- unsigned
int result = (((unsigned char) ch[7]) << 8) + ((unsigned char)ch[6]); - 00411C68
movzx eax,byte ptr [ebp-0Dh] - 00411C6C
shl eax,8 - 00411C6F
movzx ecx,byte ptr [ebp-0Eh] - 00411C73
add eax,ecx - 00411C75
mov dword ptr [ebp-20h],eax