gcc 7.2:警告:左移计数> =类型的宽度

Mar*_*ton 0 c gcc

即使我投出了每一个正确的操作数unsigned long long,警告仍然存在.不应该uint8_t << uint64_t有这样的隐式演员:(uint64_t) uint8_t << uint64_t

这个答案表明我可以提升任何一个操作数,并且整个表达式都会被强制转换unsigned long long,但这可能是错误的.

bool dgBioReadU64LE(DgBioFile *file, uint64_t *x) {
    uint8_t u[8];
    if (!dgBioReadU8v(file, LEN(u), u)) return false;
    *x = u[0]|(u[1]<<8ULL)|(u[2]<<16ULL)|(u[3]<<24ULL)|(u[4]<<32ULL)|(u[5]<<40ULL)|(u[6]<<48ULL)|(u[7]<<56ULL);
    return true;
}

bool dgBioReadU64BE(DgBioFile *file, uint64_t *x) {
    uint8_t u[8];
    if (!dgBioReadU8v(file, LEN(u), u)) return false;
    *x = u[7]|(u[6]<<8ULL)|(u[5]<<16ULL)|(u[4]<<24ULL)|(u[3]<<32ULL)|(u[2]<<40ULL)|(u[1]<<48ULL)|(u[0]<<56ULL);
    return true;
}
Run Code Online (Sandbox Code Playgroud)

Oli*_*rth 5

不应该uint8_t << uint64_t有这样的隐式演员:(uint64_t) uint8_t << uint64_t

TL; DR - 不,移位运营商很特别.

完整答案

您正在描述的行为(基本上是匹配的操作数类型)被称为C标准中通常的算术转换.1

我们看到标准要求许多运营商(例如添加剂运营商):

[6.5.6]如果两个操作数都具有算术类型,则对它们执行通常的算术转换.

但是,我们在按位移位运算符的等效部分中看不到这样的短语.我们最接近的是:

[6.5.7]对每个操作数执行整数提升.结果的类型是提升的左操作数的类型.

但是,整数促销一个不同的东西 - 他们(基本上)说任何小于的类型[unsigned] int转换为[unsigned] int.

所以编译器在这里警告是正确的.(并且我确信你可以猜到,解决方案是在左侧操作数上执行显式转换;)


1.为了这个答案的目的,我正在考虑C11(特别是N1570)规范.这种行为至少可以追溯到C99.