在C中的printf()中将int类型转换为char
结果:-48 所以我只是尝试一下,看看会发生什么,我得到了一个意想不到的结果在C中的printf()中将int类型转换为char,c,casting,C,Casting,结果:-48 所以我只是尝试一下,看看会发生什么,我得到了一个意想不到的结果 为什么是-48?它是怎么变成负数的?很简单:53200=0xCFD0和0xCF=207,对于有符号字符=48 语言律师视角: 我认为C99/C11标准中的正确参考是§6.3.1.3(重点是我的): 当整数类型的值转换为除_Bool以外的其他整数类型时,如果该值可以用新的 类型,它是不变的 否则,如果新类型是无符号的,则该值将通过重复地加上或减去一个大于该值的最大值来转换 可以在新类型中表示,直到值在 新型的 否则,新类
为什么是-48?它是怎么变成负数的?很简单:
53200=0xCFD0
和0xCF
=207,对于有符号字符
=48 语言律师视角:
我认为C99/C11标准中的正确参考是§6.3.1.3
(重点是我的):
char
类型是有问题的,因为如果它实际表示为有符号或无符号,它也是实现定义的。标准本身完全定义的唯一方法是转换为无符号字符
类型
实际观点:
假设对于您的实现
sizeof(int)==4
,并且它使用2的补码方法存储有符号整数,则数字53200
表示为:
int *int_pointer = malloc(10);
*int_pointer = 53200;
printf("The integer at byte #0 is set to: %d \n", (char) *int_pointer);
请注意,如果您只有很少的endian CPU(这可能是真实的假设),那么字节的顺序,或者更严格地说,它们在内存和CPU寄存器中的实际存储方式是颠倒的,即该数字存储为:
0000 0000 0000 0000 1100 1111 1101 0000
(无符号字符)53200
产生的是(纯数学意义上的)减法as的结果(注意,标准保证sizeof(无符号字符)==1
):
它是二进制的11010000
可以从数学上证明,结果总是与“截止”相同,只保留最后一个最低有效字节作为强制转换的结果
printf()
的注释:
正如@pmgprintf()
所指出的,它是一个可变函数,由于默认的参数提升,它的可选参数类型无符号字符
(或者有符号字符
和字符
)总是被提升到int
,但这次它“只是一种形式”
注:可供选择的双向运算符解决方案:
作为替代解决方案,您可以使用具有适当掩码的双向&
和运算符来获取特定数字的最低有效字节,例如:
53200 - 256 - 256 - ... - 256 = 53200 % 256 = 208
将一个数据类型强制转换为另一个数据类型,该数据类型的宽度不足以容纳所有可能的值,这是一种未定义的行为。对于未定义的行为,编译器可以自由地做它想做的任何事情,因此通常它会做对实现者来说最省力的事情,因为他们自动正确,而你总是错误的
因此,你不必问“为什么会这样?”——你应该庆幸没有得到52301或42,或者“救命!我被困在整数库中了!” 我认为@fritzone是正确的。
由于C中整数的范围是-32768到32767,因此在32767之后,它将变为-32768而不是32768,因此它将打印-48而不是53200。
尝试值53201,它将打印出值-47,依此类推。@grzegorzzpetkowski可能它不是标准定义的,但事实就是如此。对于这个版本的运行,这个编译器在这个操作系统上使用这些选项编译,但仍然是。@Quentin:我已经发现它实际上是实现定义的,请参阅C99/C11 6.3.1.3。我很困惑。C中从int到char的转换是否总是截断该值,只保留低位8位?@HotLicks如果目标类型是有符号的,并且该值不适合,则不会进行转换。@HotLicks否,它是实现定义的。在您有经验的系统上,您可能已经习惯了这种行为,但是C已经在很多平台上使用过。接受可变数量参数的函数的
…
部分中的参数根据需要进行转换。首先将int
类型的值转换为char
类型的值,然后将结果值隐式转换回int
。我能说的是,您的实现将char
视为有符号:)“假设对于您的实现sizeof(int)==32
。”我想,您的意思是4;)@mafso:是的,是字节,不是位,更正了,谢谢你的发现:)增加了这个答案。int_指针最多可以容纳10个字节的数据。在int_指针中存储了4个字节的数据。char数据类型只能保存1字节的数据。因此,当您将4个字节强制转换为1个字节时,会出现溢出。这就是为什么您的数字返回为-48。要添加的是:编译器在这里所做的只是将值的低8位解释为有符号的数字。我认为这里没有UB,因为在C标准中,整数类型之间的转换是定义良好的(对于有符号的类型,它的实现定义)
53200 - 256 - 256 - ... - 256 = 53200 % 256 = 208
*int_number & 0xff /* mask is 0000 0000 0000 0000 1111 1111 */