简体   繁体   English

移位计数 >= 64 位但不是 32 位的类型警告宽度

[英]shift count >= width of type warning for 64 bit but not 32 bit

I get a "shift count >= width of type" warning for test1 but I do not get this same warning for test3.我收到 test1 的“班次计数 >= 类型宽度”警告,但 test3 没有收到同样的警告。 All tests appear to work and casting gets rid of the warning.所有测试似乎都有效,并且铸造摆脱了警告。 However, I don't understand why I don't get a similar warning for test3.但是,我不明白为什么我没有收到关于 test3 的类似警告。

test1 and test2 are 64 bit long type on my machine and test3 and test4 are 32 bit int type on my machine. test1 和 test2 在我的机器上是 64 位长类型,而 test3 和 test4 在我的机器上是 32 位 int 类型。 I use similar code to this to pack/unpack data to send over a network.我使用与此类似的代码来打包/解包数据以通过网络发送。 I've rewrote it to fit this question.我重写了它以适应这个问题。

unsigned char arr1[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
unsigned char arr2[4] = {0xFF, 0xFF, 0xFF, 0xFF};
long test1;
long test2;
int test3;
int test4;

// Gives warning: shift count >= width of type
test1 = (arr1[0] << 56) | (arr1[1] << 48) | (arr1[2] << 40) | (arr1[3] << 32)
    | (arr1[4] << 24) | (arr1[5] << 16) | (arr1[6] << 8) | arr1[7];
printf("Test 1: %lX\n", test1);

// No warning
test2 = ((long)arr1[0] << 56) | ((long)arr1[1] << 48) | ((long)arr1[2] << 40)
    | ((long)arr1[3] << 32) | ((long)arr1[4] << 24) | ((long)arr1[5] << 16)
    | ((long)arr1[6] << 8) | (long)arr1[7];
printf("Test 2: %lX\n", test2);

// No warning. Shouldn't this give a warning?
test3 = (arr2[0] << 24) | (arr2[1] << 16) | (arr2[2] << 8) | arr2[3];
printf("Test 3: %X\n", test3);

// No warning
test4 = ((int)arr2[0] << 24) | ((int)arr2[1] << 16) | ((int)arr2[2] << 8)
    | (int)arr2[3];
printf("Test 4: %X\n", test4);

There's no warning in case 3 due to integer promotions .由于integer 促销,案例 3 中没有警告。

Generally speaking, when a type smaller than int is used in an expression it is first promoted to int .一般来说,当在表达式中使用小于int的类型时,它首先被提升为int For example, when you do this:例如,当您这样做时:

arr2[0] << 24

The value arr2[0] has type unsigned char , but this value is first promoted to int , then the promoted value is shifted.arr2[0]的类型为unsigned char ,但该值首先被提升为int ,然后被提升的值被移位。 So case 3 and case 4 are actually the same.所以case 3和case 4其实是一样的。

One thing to watch for here is that due to the promotion to a signed type, you could be shifting a bit with value 1 into the sign bit.这里要注意的一件事是,由于升级为有符号类型,您可能会将值为 1 的位移入符号位。 Doing so triggers undefined behavior .这样做会触发未定义的行为

The safest way to handle this is to cast each value to an unsigned type of the appropriate size before shifting, and the result should be assigned to the proper unsigned type.处理此问题的最安全方法是在移位之前将每个值强制转换为适当大小的无符号类型,并且应将结果分配给正确的无符号类型。 Also note the macros for size-specific printf format specifiers.另请注意特定于大小的printf格式说明符的宏。

unsigned char arr1[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
unsigned char arr2[4] = {0xFF, 0xFF, 0xFF, 0xFF};
uint64_t test2;
uint32_t test4;

test2 = ((uint64_t)arr1[0] << 56) | ((uint64_t)arr1[1] << 48)
      | ((uint64_t)arr1[2] << 40) | ((uint64_t)arr1[3] << 32)
      | ((uint64_t)arr1[4] << 24) | ((uint64_t)arr1[5] << 16)
      | ((uint64_t)arr1[6] << 8)  | (uint64_t)arr1[7];
printf("Test 2: %" PRIX64 "\n", test2);

test4 = ((uint32_t)arr2[0] << 24) | ((uint32_t)arr2[1] << 16) 
      | ((uint32_t)arr2[2] << 8)  | (uint32_t)arr2[3];
printf("Test 4: %" PRIX32 "\n", test4);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM