0

在下面的代码中,

#include <stdio.h>
#include<conio.h>
main()
{
    int y=-01;
    y<<=3;
    printf("%d\n",y);
    y>>=3;
    printf("%d",y);
    getch();
}

我在一本书中读到,在 y 上使用右移运算符时,根据我的编译器,可能会或可能不会保留有符号位。这是为什么?这背后的概念是什么?请详细说明。

4

4 回答 4

3

一些处理器只有“无符号”右移(用 0 填充符号位)或有符号右移(用当前符号位的副本填充大小位)。由于一些处理器只有一个或另一个,但不是两者都有,因此该标准不会尝试强制一种行为或另一种行为。

对于它的价值,许多(大多数?)当前的处理器都有指令来做这两者。例如,x86 包括shr(逻辑右移——用 0 填充)和sar(算术右移——用符号位的副本填充)。

于 2013-08-28T15:54:33.987 回答
2

以下来自 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 具有带符号类型和负值,则结果值是实现定义的。
于 2013-08-28T16:04:09.863 回答
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 位有符号整数的最大值时,您会发现编译器依赖于移位。

这里用 1 和 2 的补码表示来解释 8 位有符号整数

于 2013-08-28T16:01:07.967 回答
0

这是真实的。因为,有四种类型的变速可用。

  1. 算术移位

  2. 逻辑移位

  3. 轮换 无进位 Shift

  4. 通过进位轮换

在前两种类型中,sign-bit在向右或向左移动时保留 的位置。通常在 C 或 C 的任何派生中使用Arithmetic Shift& Logical Shift。在 C 中,Right Shiftis 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上面所有班次的标题链接的主要文章。

于 2013-08-28T16:28:33.817 回答