C语言中unsigned long与char数组互转异常:输出值不符求助
问题分析与解决方案
这个问题我之前也碰到过,本质是符号扩展在搞鬼!
具体原因
C语言有默认的整数提升规则:当你对unsigned char类型的变量进行移位操作时,它会先被提升为int类型。你的pdest[3]值是0xFF,如果系统里int是32位有符号类型,那0xFF作为int就是-1。执行pdest[3] << 24时,实际上是把-1左移24位,得到的结果是0xFFFFFFFF(在有符号int里还是-1)。
接下来把这个值赋值给unsigned long类型的l1时,C会把有符号的-1转换成无符号类型,触发符号扩展——所有高位都会被填充为1,最终得到0xFFFFFFFFFFFFFFFF,也就是你看到的18446744073709551615。
修复方案
解决方法很简单:移位前把unsigned char数组元素强制转换为unsigned long类型,让整数提升按无符号规则进行,避免符号扩展。
修正后的代码如下:
#include <stdio.h> int main(void) { unsigned char pdest[4]; unsigned long l = 0xFFFFFFFF; pdest[0] = l & 0xFF; pdest[1] = (l >> 8) & 0xFF; pdest[2] = (l >> 16) & 0xFF; pdest[3] = (l >> 24) & 0xFF; unsigned long int l1 = 0; l1 |= (unsigned long)pdest[0]; l1 |= (unsigned long)pdest[1] << 8; l1 |= (unsigned long)pdest[2] << 16; l1 |= (unsigned long)pdest[3] << 24; printf("%lu\n", l1); return 0; }
验证结果
运行这段代码后,输出就会是你预期的4294967295,也就是0xFFFFFFFF的十进制值。
补充一句:如果你的系统中unsigned long是64位,0xFFFFFFFF本身就是4294967295,但之前的代码因为符号扩展错误把它变成了64位全1值。强制转换为unsigned long后,移位操作在无符号上下文执行,就不会出问题了。
内容的提问来源于stack exchange,提问作者wizz777
相关产品推荐
相关产品推荐

