printf输出错误的数字

Jag*_*gan 2 c floating-point formatting printf

int main()
{
       double i=4;
       printf("%d",i);
       return 0;
}
Run Code Online (Sandbox Code Playgroud)

谁能告诉我为什么这个程序输出0?

Jon*_*rdy 19

当您double使用该值创建初始化时4,其64位根据IEEE-754标准填充双精度浮点数.浮点分为三个部分:符号,指数分数(也称为有效数,系数尾数).符号是一位,表示该数字是正数还是负数.其他字段的大小取决于数字的大小.要解码数字,使用以下公式:

1. 分数 ×2 指数 - 1023

在您的示例中,符号位为0,因为数字为正,小数部分为0,因为数字初始化为整数,而指数部分包含值1025(2,偏移量为1023).结果是:

1.0×2 2

或者,正如您所料,4.数字的二进制表示(分为部分)如下所示:

0 10000000001 0000000000000000000000000000000000000000000000000000

或者,以十六进制表示0x4010000000000000.将值传递给printf使用说明%d符时,它会尝试sizeof(int)从传递给它的参数中读取字节.在你的情况下,sizeof(int)4,或32位.由于您提供的64位浮点数的第一个(最右边)32位是全部0,因此它可以printf产生0整数输出.如果你要写:

printf("%d %d", i);
Run Code Online (Sandbox Code Playgroud)

然后你可能得到0 1074790400,第二个数字相当于0x40100000.我希望你明白为什么会这样.其他答案已经解决了这个问题:使用%f格式说明符并printf正确接受你的double.


Joh*_*ode 8

Jon Purdy向您详细解释了为什么您会看到这一特定结果.但是,请记住,语言标准明确地未定义该行为:

7.19.6.1.9:如果转换规范无效,则行为未定义.248) 如果任何参数不是相应转换规范的正确类型,则行为未定义.

(强调我的)"未定义的行为"的意思

3.4.3.1:使用不可移植或错误的程序结构或错误数据时的行为,本国际标准不对此要求

IOW,编译器没有义务产生有意义或正确的结果.最重要的是,您不能依赖可重复的结果.无法保证此程序在其他平台上输出0,或者甚至在具有不同编译器设置的同一平台上输出0(可能会,但您不想依赖它).