K&R C练习疑问:无符号短整型用%d输出正常,长整型却异常?
无符号短整型与长整型用
%d输出的差异原因 核心原因在于C语言的默认参数提升规则,以及printf作为可变参数函数对类型匹配的严格要求,以下分两种情况拆解:
1. unsigned short int用%d输出"正常"的本质
当你把unsigned short类型的变量传给printf时,C的默认参数提升规则会自动将其转换为int类型(因为short的长度小于等于int)。
- 在常见的32位系统中,
unsigned short的最大值是65535,这个值远小于32位int的最大值(2147483647),所以转换后的int值和原unsigned short值的二进制完全一致。 - 此时用
%d(对应有符号int)输出时,65535在int的正数范围内,因此直接输出该数值,和用%u输出无符号值的结果看起来一致。
但要注意:这只是特定环境下的巧合,属于未定义行为——标准并没有保证这种情况一定能输出正确结果,只是因为数值范围的适配才表现正常。
2. unsigned long int用%d输出错误的原因
unsigned long的长度通常等于long的长度(32位系统中为32位,64位系统中为64位),它的长度大于等于int,因此默认参数提升不会将其转换为int,而是保持unsigned long类型传递给printf。
- 当你使用
%d格式符时,printf会按照有符号int的规则去解析这个unsigned long参数。以你的测试代码为例,k = -1会被转换为unsigned long的最大值4294967295(二进制全1)。 - 32位
int的全1二进制表示是有符号数的补码,对应的值是-1,因此printf会错误地输出-1,而不是正确的无符号最大值。
总结
无论unsigned short还是unsigned long,用%d输出都是不符合标准的类型不匹配行为,只是unsigned short刚好因为参数提升和数值范围的巧合表现出"正确"结果。严格来说,输出无符号类型必须使用对应的%u(unsigned int)、%lu(unsigned long)等格式符。
内容的提问来源于stack exchange,提问作者Giorgio Vitanza
相关产品推荐
相关产品推荐

