我只是在尝试,我尝试了两个printf()s。
unsigned char a = 1;
a = ~a;
printf("----> %x %x %x %x", ~a, a, ~a, ++a);
这个给出了输出
----> ffffff00 ff ffffff00 ff
下一个是
unsigned char a = 1;
printf("----> %x %x %x %x", ~a, a, ~a, ++a);
这个给出了输出
----> fffffffd 2 fffffffd 2
现在,我知道'++'的作用和'〜'的作用。我也知道printf中的操作顺序是从右边开始的。
但有人可以解释打印字节数的差异吗?当然,对输出的完整解释会有所帮助,但我对两种情况下的字节数和差异更感兴趣[特别是在printf a和~a部分]。
编辑:
好吧,看起来像++部分和我的错误“我也知道printf内部的操作顺序来自右边”已经提示除了我希望寻找的答案之外的每个帖子。所以可能是我问的方式错了。
我会再试一次,
unsigned char a = ~1;
a = ~a;
printf("----> %x", a);
输出: ----> 1
unsigned char a = ~1;
printf("----> %x", ~a);
输出: ----> ffffff01
为什么会出现这种差异?
答案 0 :(得分:2)
printf("----> %x %x %x %x", ~a, a, ~a, ++a);
实际上会调用未定义的行为,因为您对a
和其他表达式有副作用,具体取决于相同的左值。所以任何事情都可能发生,试图解释产生的结果是没有希望的。
如果你写了
,假设在2的补码表示中有32位整数printf("----> %x %x %x %x", ~a, a, ~a, a + 1);
你会得到不同的,不那么令人惊讶的输出:
ffffff01 fe ffffff01 ff
让我解释一下发生了什么:
a = ~a;
a
包含1
,转换为具有相同值的int
,应用于~
的{{1}}运算符计算为1
,将其转换回-2
会得到254或unsigned char
。
然后计算0xfe
的参数如下:
printf
:0xfe转换为~a
并且所有位都被补充,产生int
。
0xffffff01
转换为a
并使用相同的值并打印为int
。
fe
当然再次提供相同的输出。
~a
:a+1
在递增1之前转换为a
,结果为255,打印为int
。
您惊讶输出的解释是
ff
第一次转换为a
,然后计算在int
值上完成。
答案 1 :(得分:1)
a = ~a;
您已经在此行上进行了整数提升,因为~
与C中的大多数运算符一样,根据整数提升规则提升操作数。
包含值1
的字符将整数提升提升为int
,其中包含值1
,,之后操作完成。假设32位int
,~a
的结果是负数,两个补码变量,其值为十六进制0xFFFFFFFE
。
然后将此结果显示回unsigned char,它将截断结果并仅获取最低有效字节的原始二进制值,即:0xFE
。
我也知道printf内部的操作顺序是从右边开始的。
没有。函数参数的评估顺序未在标准中指定。编译器可以按照自己喜欢的顺序自由评估它们,并且您无法知道或承担任何特定的顺序。
更有问题的是,在评估不同参数之间没有序列点。因为在您的情况下,您多次使用相同的变量,每次访问变量都是 unsequenced ,并且您的程序会调用未定义的行为。意味着任何事情都可能发生:奇怪的输出,程序崩溃,内存损坏等等。
此外,printf
是一种特殊情况,是一种模糊的,可变的函数。所有这些函数都有特定的规则来推广参数("默认参数促销")。因此,无论在将结果传递给printf之前发生或未发生什么促销,printf都会通过将自己的整数提升应用于参数来破坏所有内容。
因此,如果你想玩促销,printf是显示结果的一个非常糟糕的选择。请尝试使用sizeof
运算符。例如,printf("%zu", sizeof(~a));
将打印4,因为整数提升。