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

问题描述

在计算有符号和无符号的char,short,int和long变量范围时,我采用了以下解决方案:

  1. https://stackoverflow.com/a/19085193/11320006

  2. 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的行为有所不同?

解决方法

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

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

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

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

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

...由于%d伪指令的类型与相应的自变量不正确匹配,因此表现出未定义的行为。 %d必须与 signed int匹配,但是您已将其与unsigned int关联。实际上,UB表现为将参数的位模式解释为好像是signed int而不是无符号的,但是原则上,程序可以在其内部完成任何操作力量。

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

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

伪指令%hu将是与相应实际参数的最佳匹配,但是%d可以接受,因为上述自动类型提升。 %u不匹配。但是,在这种情况下,显示的UB与您预期的行为相同-至少在输出指示的范围内。实际上,非负signed int参数的位模式已被解释为unsigned int

,

简单-因为您使用了错误的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系列功能时始终使用正确的格式!!!使用错误的行为可能导致不确定的行为