使用格式说明符 %d 和 %u 将 ~0 类型转换为 (unsigned int) 和 (unsigned short) 会为 short 产生相同的结果,但为 int 产生不同的结果

Type casting ~0 to (unsigned int) and (unsigned short) with format specifier %d and %u produces same result for short but different result for int

在计算 char、short、int 和 long 变量(有符号和无符号)的范围时,我求助于以下解决方案:

  1. http://www.learntosolveit.com/cprogramming/Ex_2.1_cal_limits.html

根据解决方案 1,我希望下面代码中的 (unsigned short)~0 输出 -1 和 65535,假设其行为与两个格式说明符的 (unsigned int)~0 代码相同。

// the two statements below produce different results
printf("Value of unsigned int is %d\n", (unsigned int)~0); // outputs -1                                                                                                                                                     
printf("Value of unsigned int is %u\n", (unsigned int)~0); // outputs 4294967295

// whereas, the two statements below produce the same result. Why?
printf("Value of short unsigned int is %d\n", (unsigned short)~0); // outputs 65535, expected -1
printf("Value short unsigned int is %u\n", (unsigned short)~0); // outputs 65535

为什么 (unsigned short)~0(unsigned int)~0 的行为不同?

简单 - 因为您使用了错误的 printf 格式。

int main(void)
{
    printf("Value of short unsigned int is %hd\n", (unsigned short)~0); 
    printf("Value short unsigned int is %hu\n", (unsigned short)~0); 

    printf("Value of short unsigned int is %hhd\n", (unsigned char)~0); 
    printf("Value short unsigned int is %hhu\n", (unsigned char)~0); 
}

记得

使用 printf 系列函数时始终使用正确的格式!!!。使用错误的可能会导致未定义的行为

Why is there a difference in the behaviour of (unsigned short)~0 and (unsigned int)~0?

这些表达式的行为是类似的。假设 int 类型的补码表示,每个计算其(无符号)类型的最大可表示值。

但是,printf 等可变参数函数的可变参数受默认参数提升的影响。这会影响 unsigned short,如果 int 可以代表所有 unsigned short 值,则将其提升为 int,就像您的示例中的情况一样(否则为 unsigned int)。它不影响类型 intunsigned int 或更宽的整数类型的参数。

所提供代码的关键问题是...

printf("Value of unsigned int is %d\n", (unsigned int)~0);

... 由于 %d 指令未正确类型匹配到相应的参数而表现出未定义的行为。 %d 必须与 签名 int 匹配,但您已将其与 unsigned int 相关联。实际上,UB 表现为将参数的位模式解释为 signed int 而不是无符号的,但原则上,该程序可以在其范围内做任何事情电源。

请注意,由于类型不匹配,这也有未定义的行为:

printf("Value short unsigned int is %u\n", (unsigned short)~0);

指令 %hu 将是与相应实际参数的最佳匹配,但 %d 是可以接受的,因为前面提到的自动类型提升。 %u 不匹配 。然而,在这种情况下,显示的 UB 与您预期的行为相同——至少就输出所指示的而言。实际上,non-negative signed int 参数的位模式被解释为 unsigned int.