这是整数提升吗?它是如何工作的?
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+1
:a
在加一之前转换为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
的字符得到 整数提升 为包含值 1
的 int
, 之前 操作完成。假设 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,因为整数提升。
我只是在试验,我尝试了两个 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+1
:a
在加一之前转换为int
,结果为255,打印为ff
.
The explanation for your surprising outputs is that
a
is first converted toint
and then the computation is done on theint
value.
a = ~a;
您已经在这一行进行了整数提升,因为 ~
与 C 中的大多数运算符一样,根据整数提升的规则提升操作数。
包含值 1
的字符得到 整数提升 为包含值 1
的 int
, 之前 操作完成。假设 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,因为整数提升。