首页 > 解决方案 > “警告:左移计数> =类型宽度”似乎发生得太晚了

问题描述

采取以下代码片段:

#include <stdio.h>
#include <stdint.h>

void decodeStatus(uint8_t d)
{
    uint64_t a = d << 31;
    uint64_t b = d << 32;
}

uint8_t向左移动八位或更多位时,它变为 0,这会导致警告。编译器有义务确保 anuint8_t正好是 8 位(C11 规范 7.20.1.1 第 1 和第 2 节),因此两次移位都应导致警告。但显然,只有第二个班次会发出警告:

gcc -c main.c -o a.out
main.c: In function ‘decodeStatus’:
main.c:7:20: warning: left shift count >= width of type [-Wshift-count-overflow]
         uint64_t b = d << 4*8;

这是编译器错误,还是有合乎逻辑的解释?我在以下编译器上验证了这一点:

$> gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
$> arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (GCC) 9.2.0

标签: cgccwarningscompiler-warnings32-bit

解决方案


您需要转换移位的数据

uint64_t decodeStatus(uint8_t* buf)
{
    uint64_t raw = (uint64_t)buf[0] | ((uint64_t)buf[1] << (1*8))
        | ((uint64_t)buf[2] << (2*8)) | ((uint64_t)buf[3] << (3*8))
        | ((uint64_t)buf[4] << (4*8)) | ((uint64_t)buf[5] << (5*8))
        | ((uint64_t)buf[6] << (6*8)) | ((uint64_t)buf[7] << (7*8));
}

推荐阅读