我已经问了一个密切相关的question,这是一个相同的扩展案例。
请考虑以下代码:
#include<stdio.h>
int main(void)
{
char c1 = 3000.5;
printf("%d\n",c1);
}
上述代码的输出是
127
请解释右边的double值如何转换为char。 我对这个过程的理解如下:
浮点表示中的double值3000.5如下:
01000000 10100111 01110001 0000000000000000 00000000 00000000 00000000
如果我们只考虑最后8位,那么得到的二进制数是
00000000
在2的补码表示中是十进制0.这与结果不一致。
如果我们忽略小数部分,那么我们得到3000,当转换为char时,结果是-72,这又与结果不一致。
如果我对这个概念有错误的理解,请纠正我。
答案 0 :(得分:3)
发生的事情是real floating-integer conversion,会发生什么
丢弃小数部分(截断为零)。
- 如果结果值可以由目标类型表示,则使用该值
- 否则,行为未定义
由于截断值3000
很大,以适应char
undefined behavior。
答案 1 :(得分:3)
当double值超出char
范围时,C中的double to char转换规则
未定义的行为,如果double
值,一旦失去其分数,就会超出char
范围。
将3000.5转换为导致-72或127的char
是未定义行为的示例。下次运行代码时,结果可能是42或系统崩溃 - 它是UB。
像double
这样的浮点转换包含两个步骤
当实数浮动类型的有限值被转换为除
_Bool
以外的整数类型时,小数部分被丢弃(即,该值被截断为零)。如果整数部分的值不能用整数类型表示,则行为是未定义的。 C11§6.3.1.41
FP和整数的格式与指定的转换无关。
转换为带有-128到127范围的签名char
时,{-1}}的值为-128.999 ...到+127.999 ...已明确定义。不在该范围内的值会导致UB。
答案 2 :(得分:3)
除了@chux提到的,声明
char c1 = 3000.5;
未定义的行为,因为c1
是signed
字符&amp;签名字符的最大限制为127
,即范围-128 to + 127
。
在您的特定情况下,将任何大于SCHAR_MAX
的值分配给c1
会被截断为SCHAR_MAX(127)
本身。这意味着char c1 = 127.5;
和char c1 = 3000.5;
会产生相同的输出,因此输出为127
。
此外,当您使用-Wall
标志编译程序时,它可能会警告您喜欢
隐式常量转换溢出[-Werror = overflow]
所以答案就是警告本身。建议您认真注意编译器警告&amp;将所有警告视为错误。
gcc -Wall -Wstrict-prototypes -Werror test.c