这是整数提升吗?它是如何工作的?

Is this Integer Promotion? How does it work?

我只是在试验,我尝试了两个 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 部分]。

编辑:

好的,看起来像 ++ 部分,我的 "I also know that the sequence of operation inside printf is from the right" 错误提示了所有 post,而不是我希望寻找的答案。所以可能是我问的方式不对。

我会再试一次,

unsigned char a = ~1;
a = ~a;
printf("----> %x", a); 

输出:----> 1

unsigned char a = ~1;
printf("----> %x", ~a);

输出:----> ffffff01

为什么会有这种差异?

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~ 运算符计算为 -2,将其转换回 unsigned char 得到 254 或 0xfe.

printf 的参数计算如下:

  • ~a:0xfe 被转换为 int 并且所有位被补码,产生 0xffffff01.

  • a 转换为具有相同值的 int 并打印为 fe.

  • ~a 再次给出相同的输出。

  • a+1a在加一之前转换为int,结果为255,打印为ff.

The explanation for your surprising outputs is that a is first converted to int and then the computation is done on the int value.

a = ~a; 您已经在这一行进行了整数提升,因为 ~ 与 C 中的大多数运算符一样,根据整数提升的规则提升操作数。

包含值 1 的字符得到 整数提升 为包含值 1int 之前 操作完成。假设 32 位 int~a 的结果是一个负数,具有十六进制值 0xFFFFFFFE.

的两个补码变量

然后将此结果显示回 unsigned char,它将截断结果并仅获取最低有效字节的原始二进制值,即:0xFE.

I also know that the sequence of operation inside printf is from the right.

没有。标准未指定函数参数的评估顺序。编译器可以按照它喜欢的任何顺序自由计算它们,您无法知道或假设任何特定顺序。

更有问题的是,不同参数的求值之间没有序列点。并且由于在您的情况下您不止一次使用同一个变量,因此每次访问该变量都是 unsequenced 并且您的程序会调用未定义的行为。这意味着任何事情都可能发生:奇怪的输出、程序崩溃、内存损坏等。

此外,printf 是一个特殊情况,是一个模糊的可变函数。所有这些函数都有特定的参数提升规则 ("the default argument promotions")。因此,无论在将结果传递给 printf 之前发生或不发生什么提升,printf 都会通过对参数应用它自己的整数提升来破坏一切。

所以如果你想玩弄促销,printf 是显示结果的一个非常糟糕的选择。请尝试改用 sizeof 运算符。 printf("%zu", sizeof(~a)); 例如会打印 4,因为整数提升。