在以下代码中,
#include <stdio.h>
#include<conio.h>
main()
{
int y=-01;
y<<=3;
printf("%d\n",y);
y>>=3;
printf("%d",y);
getch();
}
我在一本书中读到,在y上使用右移位运算符时,根据我的编译器,可能会也可能不会保留有符号位。这是为什么?这背后的概念是什么?请详细说明。
答案 0 :(得分:3)
某些处理器只有“无符号”右移(用0填充符号位)或有符号右移(用当前符号位的副本填充大小位)。由于某些处理器只有一个或另一个,但不是两者,标准不会尝试强制执行一种行为或另一种行为。
对于它的价值,许多(大多数?)当前处理器都有指令同时执行这两项操作。例如,x86包括shr
(逻辑右移 - 填充0)和sar
(算术右移 - 填充符号位的副本)。
答案 1 :(得分:2)
C11标准中的以下引用( 6.5.7按位移位运算符)可能会有所帮助:
- E1&lt;&lt; E2 是E1左移E2位位置;腾出的位用零填充。如果E1具有无符号类型,则结果的值为 E1×2 ^ E2 ,比结果类型中可表示的最大值减少一个模数。如果E1具有带符号类型和非负值,并且 E1×2 ^ E2 在结果类型中可表示,那么这就是结果值;否则,行为未定义。
- E1&gt;的结果&gt; E2 是E1 右移 E2位位置。如果E1具有无符号类型或者E1具有有符号类型和非负值,则结果的值是 E1 / 2 ^ E2 的商的整数部分。 如果E1具有签名类型和负值,则结果值是实现定义的。
答案 2 :(得分:0)
让我们看看这个例子
考虑此值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位有符号整数的最大值时,您会发现编译器依赖于移位。
这里的8位有符号整数用1和2的恭维表示来解释 Signed number representations
答案 3 :(得分:0)
这是事实。因为,有四种类型的转移。
在前两种类型中,sign-bit
的位置在向右或向左移动时保留。通常在C或C的任何推导中使用Arithmetic Shift
&amp; Logical Shift
。在C中,Right Shift
是Arithmetic Shift
&amp; Left Shift
是逻辑的。但在Java中,两者都是Logical Shifting
。
在最后两种类型中,不保留Sign Bit
的位置。这些位以常规方式移位。 Rotate No Carry
属于Circular Shift,主要用于加密以保留所有位。
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
主要文章,该文章与上述所有轮班的标题相关联。