C语言中按位取反对数值与变量的行为差异技术咨询
无符号字符取反结果差异的问题解析
遇到的现象
运行代码后得到如下输出:
test1: 0x00000002 0b00000010 (1 bytes) test2: 0x000000fd 0b11111101 (1 bytes) ~test1: 0xfffffffd 0b4294967285 (4 bytes)
我无法理解为何在所有类型均为无符号的情况下,~test1与~(0x02)的结果不同——test1的值就是0x02,但~test1在正确取反后左侧多了3字节的1。
问题代码
#include <stdio.h> int binConv(int num) { if (num == 0) { return 0; } else { return (num % 2) + 10 * binConv(num / 2); } } int main() { unsigned char test1; unsigned char test2; test1=0x02; test2=~(0x02); printf(" test1: 0x%08x 0b%08u (%d bytes)\n",test1,binConv(test1),sizeof(test1)); printf(" test2: 0x%08x 0b%08u (%d bytes)\n",test2,binConv(test2),sizeof(test2)); printf("~test1: 0x%08x 0b%08u (%d bytes)",~test1,binConv(~test1),sizeof(~test1)); return 0; }
问题拆解与解答
这事儿其实是C语言里的**整数提升(Integer Promotion)**在搞鬼,我给你一步步说清楚:
先看
~(0x02)的逻辑0x02是整数字面量,C语言默认把它当成int类型(通常是4字节)。对它取反后得到0xfffffffd,但当把这个值赋值给unsigned char类型的test2时,会自动截断——只保留低8位的0xfd(二进制11111101),所以最终test2的输出是符合预期的1字节结果。再看
~test1的逻辑test1是unsigned char(1字节),当你对它使用~运算符时,C语言会触发整数提升规则:把小于int的整数类型自动转换成int类型。所以test1的0x02会先被转成int类型的0x00000002,再取反得到0xfffffffd——这个结果直接传给了printf,没有经过截断,所以你看到的是4字节的数值,也就是左侧多了3字节的1。而且sizeof(~test1)输出4也能证明:取反后的结果已经是int类型,不再是原来的unsigned char了。怎么让
~test1和~(0x02)输出一致?
只要把~test1强制转回unsigned char类型就行,比如修改最后一行printf:printf("~test1: 0x%08x 0b%08u (%d bytes)",(unsigned char)~test1,binConv((unsigned char)~test1),sizeof((unsigned char)~test1));这时候输出就会和test2完全一样啦。
内容的提问来源于stack exchange,提问作者Yelneerg
相关产品推荐
相关产品推荐

