macOS 10.12 C语言右移与Ubuntu16.04不同

Bit right shifting of C language in macOS 10.12 is different from Ubuntu 16.04

更新: 我刚刚在 macOS 上的新 C 源文件中重写了函数:

#include <stdio.h>

int main() {

int x = 0xffffffff;

int m2 = (((((0x55 << 8) + 0x55 )<< 8) + 0x55)<< 8) + 0x55;
printf("m2 : 0x%x\n",m2);

int m4 = (((((0x33 << 8) + 0x33 )<< 8) + 0x33)<< 8) + 0x33;
printf("m4 : 0x%x\n",m4);

int m8 = (((((0x0f << 8) + 0x0f )<< 8) + 0x0f)<< 8) + 0x0f;
printf("m8 : 0x%x\n",m8);

int m16 = (0xff << 16) + 0xff ;
printf("m16 : 0x%x\n",m16);

int p1 = (x & m2) + ((x >> 1) & m2);
printf("p1: 0x%x\n",p1);

printf("p1 & m4 : 0x%x\n",p1 & m4);

printf("p1 >> 2 : 0x%x\n",p1 >> 2);

printf("(p1 >> 2) & m4 : 0x%x\n",(p1 >> 2) & m4);

int p2 = (p1 & m4) + ((p1 >> 2) & m4);
printf("p2 : 0x%x\n",p2);

int p3 = (p2 & m8) + ((p2 >> 4) & m8) ;
printf("p3 : 0x%x\n",p3);

int p4 = (p3 & m16)  + ((p3 >> 8) & m16) ;
printf("p4 : 0x%x\n",p4);
//int p4 = p3   + (p3 >> 8)  ;
int p5 = p4 + (p4 >> 16) ;

printf("BigCount result is : 0x%x\n",p5 & 0xFF);
}

打印结果为:

一切都和Ubuntu中的一样。这让我更加困惑。


当我在 macOS 10.12 中 运行 这个功能时,它给出了意想不到的答案。输入 x0xffffffff (-1)。 函数用C语言写成:

int bitCount(int x) {

  int m2 = (((((0x55 << 8) + 0x55 )<< 8) + 0x55)<< 8) + 0x55;
  int m4 = (((((0x33 << 8) + 0x33 )<< 8) + 0x33)<< 8) + 0x33;
  int m8 = (((((0x0f << 8) + 0x0f )<< 8) + 0x0f)<< 8) + 0x0f;
  int m16 = (0xff << 16) + 0xff ;

  int p1 = (x & m2) + ((x >> 1) & m2);
  int p2 = (p1 & m4) + ((p1 >> 2) & m4); //line 7
  int p3 = (p2 & m8) + ((p2 >> 4) & m8) ;
  int p4 = (p3 & m16)  + ((p3 >> 8) & m16) ;
  //int p4 = p3   + (p3 >> 8)  ;
  int p5 = p4 + (p4 >> 16) ;

  return p5 & 0xFF;
}

当我通过打印跟踪所有局部变量时,我发现:

((p1 >> 2) & m4) //line7

打印'0x2222222'的值(七个'2'而不是八个'2')。

这太出乎意料了,p1 打印 '0x2aaaaaaa' 而 m4 是 '0x33333333',所以它应该是 0x22222222(8 '2;)。 但是,当我在 ubuntu 16.04 中 运行 时,一切都如预期的那样,因为 ((p1 >> 2) & m4) 打印“0x22222222”:

您 运行 您的 Mac 是否遇到同样的问题? macOS 中有什么不同会导致这个问题吗?

根据 C 标准的 6.5.7 Bitwise shift operators(注意突出显示的部分):

Constraints

2 Each of the operands shall have integer type.

Semantics

3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 x 2E2 , reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 x 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2 . If E1 has a signed type and a negative value, the resulting value is implementation-defined.

您正在对有符号 整数值进行位移。根据您的输入,您同时依赖于未定义和实现定义的行为。

在不同的平台上会有不同的结果。