【问题标题】:Arithmetic Right Shift in CC中的算术右移
【发布时间】:2012-10-04 22:00:42
【问题描述】:

在 C 语言中,在 32 位机器上,我只是想知道 1>>31 是否返回 -1 给定 1 是有符号整数,因为对于 2 的补码,在进行右移(算术)时,符号位被复制给出结果

1111 1111 1111 1111 1111 1111 1111 1111

【问题讨论】:

    标签: c bit-manipulation bit-shift


    【解决方案1】:

    不,在任何符合要求的实现中,结果都将为零。

    C99, 6.5.7/5(“按位移位运算符”)状态:

    E1 >> E2 的结果是 E1 右移 E2 位位置。如果 E1 有 一个无符号类型,或者如果 E1 有一个有符号类型和一个非负值, 结果的值是 E1 / 商的整数部分 2^E2。如果 E1 有带符号类型和负值,则结果值 是实现定义的。

    由于1 是非负数,因此结果是1 / (2^31) 的积分商,显然为零。

    【讨论】:

    • 整数1的符号位是0...不是吗?即使它是一个负数,结果也是“实现定义的”,如答案主体中 C 标准的引用中所述。
    【解决方案2】:

    结果将为零,因为整数 1 的符号位(最高有效位)为 0:

    0000 0000 0000 0000 0000 0000 0000 0001
    ^
    

    【讨论】:

      【解决方案3】:

      1>>31 的结果为零,因为 1 的符号位为 0。

      但是,您不能指望被复制的符号位,因为根据 K&R 第二版,结果是针对有符号值的右移实现定义的。

      【讨论】:

        【解决方案4】:

        对于使用二进制补码表示ints 的实现,以下代码有助于确定右移是否是有符号整数的算术运算。

        #include <stdio.h>
        
        //below function returns 1 if system is little endian, 0 otherwise
        int is_little_endian() { //checks endianness
          short x = 0x0100; //256
          char *p = (char*) &x;
          if (p[0] == 0) {
            return 1; 
          }
          return 0;
        }
        
        /* Below function returns 1 if shifts are arithmetic, 0 otherwise.
           It checks whether the most significant bit is 1 or 0, for an int which
           had most the significant bit as 1 prior to the right shift. If the MSB
           is 1 after the bit shift, then the (unsigned) value of the most
           significant Byte would be 255.
        */
        
        int int_shifts_are_arithmetic() {
          int x = -2;
          x = x >> 1 ;
          char *px = (char*)&x;
          if (is_little_endian()) {
            unsigned char *upx = (unsigned char*)&px[(int)sizeof(int) - 1];
            if (upx[0] == 255) return 1; 
            return 0;
          } else { //big endian
            unsigned char* upx = (unsigned char*)px;
            if (upx[0] == 255) return 1;
            return 0;
          }
        }
        
        int main() {
          if (int_shifts_are_arithmetic()) {
            printf("Shifts are arithmetic\n");
          }
          else {
            printf("Shifts are not arithmetic\n");
          }
          return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 2017-11-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-26
          相关资源
          最近更新 更多