printf输出错误的数字

int main() { double i=4; printf("%d",i); return 0; } 

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

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

1. 分数 ×2 指数 – 1023

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

1.0×2 2

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

  0 10000000001 0000000000000000000000000000000000000000000000000000 

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

 printf("%d %d", i); 

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

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

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

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

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

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

%d代表整数:

 int main() { int i=4; double f = 4; printf("%d",i); // prints 4 printf("%0.f",f); // prints 4 return 0; } 

因为这种语言让你搞砸了,你很乐意这样做。

更具体地说,’%d’是int的格式,因此printf(“%d”)消耗的参数与int所占的字节数一样多。 但是double要大得多,所以printf只会得到一堆零。 使用’%lf’。

因为"%d"指定要打印int ,但idouble 。 试试printf("%f\n"); 相反( \n指定换行符)。

你的问题的简单答案是,正如其他人所说,你告诉printf打印一个整数 (例如int类型的变量),同时传递一个双精度数字 (因为你的变量属于这种类型) double ),这是错的。

这是printf(3) linux程序员手册中的一个片段,解释了%d%f 转换说明符

  d, i The int argument is converted to signed decimal notation. The precision, if any, gives the minimum number of digits that must appear; if the converted value requires fewer digits, it is padded on the left with zeros. The default precision is 1. When 0 is printed with an explicit precision 0, the output is empty. f, F The double argument is rounded and converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is explicitly zero, no decimal-point character appears. If a decimal point appears, at least one digit appears before it. 

要使当前代码正常工作,您可以做两件事。 已经提出了第一个替代方案 – 用%f替换%d

你可以做的另一件事是将你的double转换为int ,如下所示:

printf("%d", (int) i);

Jon Purdy简单地回答了更为复杂的答案(解决为什么printf像它一样)。 有关更深入的解释,请查看与浮点运算和双精度相关的维基百科文章。

因为我是一个双,你告诉printf使用它就好像它是一个int(%d)。

@jagan ,关于子问题:

什么是最左边的第三个字节。 为什么是00000001? 有人可以解释一下吗?“

10000000001用于二进制格式的1025