使用unsigned long long签名扩展

use*_*970 5 c

我们发现了一些奇怪的值,下面是一个小测试用例.这将打印"FFFFFFFFF9A64C2A".这意味着无符号的长长似乎已被标记延长.但为什么 ?下面的所有类型都是无符号的,那么符号扩展的是什么?预期输出为"F9A64C2A".

#include <stdio.h>

int main(int argc,char *argv[])
{
    unsigned char a[] = {42,76,166,249};

    unsigned long long ts;
    ts = a[0] | a[1] << 8U | a[2] << 16U | a[3] << 24U;

    printf("%llX\n",ts);


    return 0;

}
Run Code Online (Sandbox Code Playgroud)

und*_*gor 5

在表达式中a[3] << 24U,a[1] 有类型unsigned char.现在,"整数提升"将其转换为int:

以下内容可用于任何地方intunsigned int可能使用的表达式:

[...]

如果a int可以表示原始类型的所有值,则该值将转换为int; 否则,它被转换为unsigned int.

((草案)ISO/IEC 9899: 1999,6.3.1.1 2)

请注意,移位运算符(除了大多数其他运算符之外)执行将两个操作数转换为通用类型的"通常算术转换".但

结果的类型是提升的左操作数的类型.

(6.5.7 3)

在32位平台上,249 << 24 = 4177526784解释为int已设置其符号位.

只是改为

ts = a[0] | a[1] << 8 | a[2] << 16 | (unsigned)a[3] << 24;
Run Code Online (Sandbox Code Playgroud)

解决问题(U常量的后缀没有影响).