在下面的代码中,
#include <stdio.h>
#include<conio.h>
main()
{
int y=-01;
y<<=3;
printf("%d\n",y);
y>>=3;
printf("%d",y);
getch();
}
我在一本书中读到,在 y 上使用右移运算符时,根据我的编译器,可能会或可能不会保留有符号位。这是为什么?这背后的概念是什么?请详细说明。
在下面的代码中,
#include <stdio.h>
#include<conio.h>
main()
{
int y=-01;
y<<=3;
printf("%d\n",y);
y>>=3;
printf("%d",y);
getch();
}
我在一本书中读到,在 y 上使用右移运算符时,根据我的编译器,可能会或可能不会保留有符号位。这是为什么?这背后的概念是什么?请详细说明。
一些处理器只有“无符号”右移(用 0 填充符号位)或有符号右移(用当前符号位的副本填充大小位)。由于一些处理器只有一个或另一个,但不是两者都有,因此该标准不会尝试强制一种行为或另一种行为。
对于它的价值,许多(大多数?)当前的处理器都有指令来做这两者。例如,x86 包括shr
(逻辑右移——用 0 填充)和sar
(算术右移——用符号位的副本填充)。
以下来自 C11 标准(6.5.7 位移位运算符)的引用可能会有所帮助:
- E1 << E2的结果是 E1 左移 E2 位位置;空出的位用零填充。如果 E1 具有无符号类型,则结果的值为E1 × 2^E2,以比结果类型中可表示的最大值多一个模数减少。如果 E1 具有带符号类型和非负值,并且E1 × 2^E2在结果类型中是可表示的,那么这就是结果值;否则,行为未定义。
- E1 >> E2的结果是 E1右移E2 位位置。如果 E1 具有无符号类型或 E1 具有有符号类型和非负值,则结果的值是E1 / 2^E2商的整数部分。如果 E1 具有带符号类型和负值,则结果值是实现定义的。
让我们看看这个例子
考虑这个值 1111 1111 1111 1111
如果你的编译器是 16 位的,你做了右移
价值会变成1111 1111 1111 1110
如果你的编译器是 32 位的并且你做了右移
价值会变成 0000 0000 0000 0001 1111 1111 1111 1110
你做了相同值的右移,但你会得到不同的结果,具体取决于你的编译器。
使用%x打印十进制值的十六进制表示法。
看到这段代码:
#include <stdio.h>
main()
{
int y=-01;
printf("%d\n",y);
printf("%x\n",y);
y<<=3;
printf("%d\n",y);
printf("%x\n",y);
y>>=3;
printf("%d\n",y);
printf("%x\n",y);
y=127;
printf("%d\n",y);
printf("%x\n",y);
y<<=3;
printf("%d\n",y);
printf("%x\n",y);
y>>=3;
printf("%d\n",y);
printf("%x\n",y);
y=32767;
printf("%d\n",y);
printf("%x\n",y);
y<<=3;
printf("%d\n",y);
printf("%x\n",y);
y>>=3;
printf("%d\n",y);
printf("%x\n",y);
getchar();
}
在 64 位机器上输出:
-1 ffffffff -8 fffffff8 -1 ffffffff 127 7f 1016 3f8 127 7f 32767 7fff 262136 3fff8 32767 7fff
32 位机器上的输出:
-1 ffffffff -8 fffffff8 -1 ffffffff 127 7f 1016 3f8 127 7f 32767 7fff -8 fffffff8 -1 ffffffff
当达到 32 位有符号整数的最大值时,您会发现编译器依赖于移位。
这里用 1 和 2 的补码表示来解释 8 位有符号整数
这是真实的。因为,有四种类型的变速可用。
在前两种类型中,sign-bit
在向右或向左移动时保留 的位置。通常在 C 或 C 的任何派生中使用Arithmetic Shift
& Logical Shift
。在 C 中,Right Shift
is Arithmetic Shift
&Left Shift
是逻辑的。但在 Java 中,两者的转变都是Logical Shifting
.
在最后两种类型中,Sign Bit
不保持定位。这些位以规则的方式移动。Rotate No Carry
属于循环移位,主要用于密码学以保留所有位。
C 编程虽然实现了Logical & arithmetic Shift
,但它也有能力Circular Shifting
通过以下方式识别:
unsigned int x;
unsigned int y;
/* This Code is Just for reference from Wikipedia */
y = (x << shift) | (x >> (sizeof(x)*CHAR_BIT - shift));
我这个信息还不够,那么你可以通过Wikipedia
上面所有班次的标题链接的主要文章。