Bitshifts抵消,而不是预期的行为
的,我注意到一些奇怪的行为与支架Bitshifts抵消,而不是预期的行为
bitshifting#include <stdio.h>
int main(void)
{
unsigned char c;
unsigned char d;
c = 153;
c = (c << 7) >> 7;
printf("%d\n", c);
d = 153;
d = (d << 7);
d = (d >> 7);
printf("%d\n", d);
}
输出:
153
1
我预计c
也有1 ...值怎么回事上?这是不确定的?
位移char
自动将其升级到int
。这就是为什么7位左移不能切断任何东西。
部6.5.7整数优惠在每个操作数的执行。结果的类型是 升级左操作数的类型。如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为未定义。
不错的答案,比我快,+ 1 – gsamaras
耶谢谢。我现在也选择使用'c =(unsigned char)(c > 7;'它给了我预期的输出 –
它被评估为int
,然后存储为char
。并且在中间步骤不是char
。换句话说,当你移位char
时,它会被提升为int
。
检查什么标准6.5.7 Bitwise shift operators有说:
的整数促销活动在每个操作数的执行。
结果的类型是提升的左操作数的类型。
如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为为 未定义。
按照什么this comment表明,我们来看看这是对平台的x86生成表达c = (c << 7) >> 7
代码:
movzbl 31(%esp), %eax ;eax = c
sall $7, %eax ;left shift
sarl $7, %eax ;right shift
movb %al, 31(%esp) ;c = al (one byte)
的c
内容被加载到32 (eax
),并且这两个移位都在该寄存器上执行。最后,该寄存器的最低有效字节(即al
)被分配给变量c
。
简而言之,两个移位都被评估为操作数是32位宽。
根据this online c standard draft,按位移位运算促进参数为整数类型:
6.5。7位移位运算符
2每个操作数应具有整数类型。
3对每个操作数执行整数提升。
所以当你写c = (c << 7) >> 7
,的c
在表达(c << 7)
的值首先被转换为一个整数值,然后移动。因此,没有一点会迷失。将它们移回>> 7
给出原始值。
当您编写d = (d << 7)
时,相反,一旦将(积分)结果重新分配给d
(这是一个无符号字符并且因此无法保持整数值的“高位”位),位会丢失。
153
in binary representation is 10011001
。按位移操作符的操作数应该有int
类型,否则将发生整数提升。
For语句
c = (c << 7) >> 7;
c
被促进为整数,并假设为整数表示4个字节,c
将00000000 00000000 00000000 10011001
二进制。所以表达式
c = (c << 7) >> 7; // Left and right shift operator will nullify the effect of each other.
将有表达
c = c;
的效果在
d = (d << 7);
d = (d >> 7);
情况下,第一条语句d
后会有值(二进制)10000000
。在第二个陈述后d
将有值(二进制)00000001
。
看看生成的代码以及它的功能。 –
与[this]类似(https://stackoverflow.com/questions/33068985/sizeof-an-integer-expression-in-c)问题。表达式被评估为一个整数,然后存储为char。与中间步骤中的字符对比。 – matt
没问题,lemmi只能使用类型转换 –