【发布时间】:2020-10-12 16:54:27
【问题描述】:
在计算 char、short、int 和 long 变量(包括有符号和无符号)范围的过程中,我采用了以下解决方案:
根据解决方案 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 的行为会有所不同?
【问题讨论】:
-
与可变参数“扩展”有关。所以它就像
(int)(unsigned short)~0。 -
65535可以被int持有,但4294967295不能。 -
%d用于int。它会将传递的任何值视为int。格式说明符和参数不匹配(例如为%d传递unsigned int)会导致未定义的行为。 -
可变参数函数的参数经过default argument promotions。这意味着任何小于
int(有符号或无符号都无关紧要)的整数值都将是promoted to anint。 -
扩大整数转换应该尝试并保持价值。这意味着扩大无符号将对其进行零扩展,而扩大有符号将对其进行符号扩展。当转换对象不适合时转换为有符号是实现定义的,但实际上您可以依靠 2 的补码重新解释。格式说明符与相应参数的类型不匹配在技术上是 UB。
标签: c casting bitwise-operators twos-complement ones-complement