在C中的printf()中将int类型化为char
int *int_pointer = malloc(10); *int_pointer = 53200; printf("The integer at byte #0 is set to: %d \n", (char) *int_pointer);
结果:-48
所以我只是试着看看会发生什么,我得到了这个意想不到的结果。
为什么-48? 怎么会变成负面的?
语言 – 律师观点:
我认为C99 / C11标准中的正确参考是§6.3.1.3
(重点是我的):
- 当具有整数类型的值转换为除_Bool之外的另一个整数类型时,如果该值可以由新类型表示,则它将保持不变。
- 否则,如果新类型是无符号的 ,则通过重复地添加或减去一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内。
- 否则,新类型将被签名 ,并且值无法在其中表示 ; 结果是实现定义的,或者引发实现定义的信号 。
请注意, char
类型存在问题,因为如果它实际上表示为有符号或无符号,它也是实现定义的。 标准本身完全定义的唯一方法是转换为unsigned char
类型。
实践观点:
假设您的实现sizeof(int) == 4
并且它使用二进制补码方法来存储有符号整数,则数字53200
表示为:
0000 0000 0000 0000 1100 1111 1101 0000
请注意,如果你有小端CPU(可能是它的真实假设),那么字节顺序,或者更严格的是它们实际存储在内存和CPU寄存器中的方式是反转的,即该数字存储为:
0000 1101 1111 1100 0000 0000 0000 0000
什么(unsigned char) 53200
产生的是(纯数学意义上)减法的结果(注意标准保证sizeof(unsigned char) == 1
):
53200 - 256 - 256 - ... - 256 = 53200 % 256 = 208
这是二进制1101 0000
可以在数学上certificate结果总是与“截止”相同,仅作为强制转换的最后,最低有效字节。
printf()
注意事项:
正如@pmg指出的printf()
是可变参数函数,并且由于默认参数提升,其unsigned char
类型的可选参数(或者signed char
和char
) 总是被提升为int
,但这次它只是“一种forms”。
注意替代双向运算符解决方案:
作为替代解决方案,您可以使用biwise &
和 operator使用适当的掩码来获取特定数字的最低有效字节,例如:
*int_number & 0xff /* mask is 0000 0000 0000 0000 1111 1111 */
将数据类型转换为另一种不足以容纳所有可能值的数据类型是未定义的行为。 对于未定义的行为,编译器可以随心所欲地执行任何操作,因此通常它会为实现者执行最少的工作,因为它们是自动正确的并且您总是错误的。
因此,你不要问“为什么会这样?” – 你应该很高兴你没有得到52301,或42,或“帮助!我被困在整数库中!” 代替。
这很简单: 53200 = 0xCFD0
和0xCF
= 207,对于有signed char
= -48 …
我认为@fritzone是正确的..
由于C中整数的范围是-32768 to 32767
,因此在32767之后它将是-32768而不是32768,因此它在53200处打印-48。
尝试值53201,它将打印出值-47,依此类推。