嘿,我试图在浏览和阅读网络后找出-1 << 4
(左)移位FFF0
的原因,我才知道“负”数字有一个符号位,即1。所以因为"-1"
意味着额外的1
位,即(33)位,这是不可能的,这就是为什么我们将-1
视为1111 1111 1111 1111 1111 1111 1111 1111
例如:-
#include<stdio.h>
void main()
{
printf("%x",-1<<4);
}
在此示例中,我们知道–
Internal representation of -1 is all 1’s 1111 1111 1111 1111 1111 1111 1111 1111 in an 32 bit compiler.
When we bitwise shift negative number by 4 bits to left least significant 4 bits are filled with 0’s
Format specifier %x prints specified integer value as hexadecimal format
After shifting 1111 1111 1111 1111 1111 1111 1111 0000 = FFFFFFF0 will be printed.
上述来源 http://www.c4learn.com/c-programming/c-bitwise-shift-negative-number/
答案 0 :(得分:6)
首先,根据C标准,未定义带负号有符号变量的左移结果。因此,从严格的语言律师角度来看,问题“ 为什么-1 << 4
导致XYZ ”的答案是“ ”,因为标准未指定结果应该是什么。 ”
但是,您的特定编译器实际上在做什么,将two's-complement representation的-1左移,就好像该表示形式是无符号值一样。由于-1的32位二进制补码表示为0xFFFFFFFF
(或二进制形式的11111111 11111111 11111111 11111111
),所以将左移4位的结果为0xFFFFFFF0
或11111111 11111111 11111111 11110000
。这是将结果存储回(有符号)变量中的结果,该值是-16的二进制补码表示。如果将结果打印为整数(%d
),则结果为-16。
这是大多数现实世界中的编译器会执行的操作,但并不依赖它,因为C标准不需要它。
答案 1 :(得分:4)
首先,教程使用void main
。在评估本教程的质量时,comp.lang.c
frequently asked question 11.15应该引起关注:
问:我一直在使用的《 C语言编程傻瓜》 一书始终使用
void main()
。A:也许作者认为自己是目标受众。许多书籍在示例中都不必要地使用
void main()
,并断言它是正确的。他们错了,或者他们假设每个人都为能正常工作的系统编写代码。
也就是说,该示例的其余部分是不明智的。 C标准未定义有符号左移的行为。但是,允许编译器实现定义针对标准故意开放的情况下的行为。例如,GCC does define
<<
在带负号的数字上定义明确,>>
的工作方式就像带符号扩展名一样。因此,保证在 GCC 上-1 << 4
产生-16
;给定32位int
,这些数字的位表示分别为1111 1111 1111 1111 1111 1111 1111 1111
和1111 1111 1111 1111 1111 1111 1111 0000
。
现在,这里还有另一个未定义的行为:%x
期望的参数为unsigned int
,但是您传入的是signed int
, unsigned int
中无法表示的值。但是,在GCC /上具有常见libc 的行为是有符号整数的字节被解释为无符号整数,1111 1111 1111 1111 1111 1111 1111 0000
以二进制形式出现,十六进制为{{1} }。
但是,可移植的C程序实际上应该从不
FFFFFFF0
甚至是unsigned int
uint32_t
或<<
具有一定的行为>>
和带签名的数字%x
。具有相同行为的,针对相同用例的可移植(C99,C11,C17)程序将是
void main