这是整数促销吗?它是如何工作的?

时间:2015-12-09 11:50:33

标签: c printf unsigned-char integer-promotion

我只是在尝试,我尝试了两个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

为什么会出现这种差异?

2 个答案:

答案 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当然再次提供相同的输出。

  • ~aa+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,因为整数提升。