Floating point 浮点访问说明符的行为与预期不符 #包括 int main() { printf(“%f”,5); }
此代码正在打印0.000000。任何人都能解释为什么会发生这种情况。Floating point 浮点访问说明符的行为与预期不符 #包括 int main() { printf(“%f”,5); },floating-point,Floating Point,此代码正在打印0.000000。任何人都能解释为什么会发生这种情况。%f格式需要一个double参数,您正在传递一个int。这是未定义的行为,任何事情都可能发生。你很幸运,所发生的只是0.00000的印刷 在C语言中,变量函数不知道在调用位置传递给它们的参数的类型。对于printf,他们只能信任格式字符串来提供该信息。任何好的编译器都应该在参数类型和(编译时已知的)格式字符串不匹配时发出警告,我很惊讶你们的不匹配。函数的实现可以依赖于已应用的默认参数提升,但仅此而已 在实践中,两种常见的情况是参
%f
格式需要一个double
参数,您正在传递一个int
。这是未定义的行为,任何事情都可能发生。你很幸运,所发生的只是0.00000的印刷
在C语言中,变量函数不知道在调用位置传递给它们的参数的类型。对于printf
,他们只能信任格式字符串来提供该信息。任何好的编译器都应该在参数类型和(编译时已知的)格式字符串不匹配时发出警告,我很惊讶你们的不匹配。函数的实现可以依赖于已应用的默认参数提升,但仅此而已
在实践中,两种常见的情况是参数在堆栈上传递,在这种情况下,在调用站点推送的
int
值5
将被解释为64位双精度
,或者参数通过寄存器传递,在这种情况下,printf
函数将从浮点寄存器中获取一个double
值,该值未在调用站点设置,并且包含上次使用时留在那里的值。这称为未定义行为,因为“%f”需要一个float或double,而您给它的是整数5
未定义的行为意味着编译器可以做任何合法的事情来处理这种情况
要解决此问题,您有三个选项:
printf(“%i”,5)
printf(“%f”,5.0)
printf(“%f”,(双)5)
这是因为在您的示例中,
5
是一个整数,而不是浮点。因此,当您使用格式字符串%f
将其传递给printf
时,您会得到未定义的行为。要使其成为浮点,请使用浮点(5.0
)声明它。这将为您提供预期的输出
例子:
%f
是double
类型(或float
,它在变量参数列表中自动升级为double
)的格式说明符,但您要向它传递一个int
。正如其他回答者正确指出的那样,这是未定义的行为
但是为什么输出是零而不是其他垃圾值呢?这需要了解一些最常见的问题
最有可能发生的情况是,您(可能)的32位int
值将零扩展为64位双
值,这样额外的32位零将填充符号位、11位指数和有效位的前20位。这导致一个值非常接近于零,以至于定点%f
格式将其四舍五入到0.00000
。使用%e
或%g
格式可能会显示一个小但非零值
同样,这只是一个实现细节,不同的C实现可能会给出不同的输出,或者导致分段错误
你可能想写的是
(为printf(“%f”,5.0)
格式使用正确的数据类型),或%f
(为printf(“%d”,5)
类型使用正确的格式字符串)int
为防止意外使用不匹配的
printf
调用,如printf(“%f”,5)
,启用编译器警告(例如,将-Wall
选项与GCC一起使用),编译程序时要注意它们。因为int显示为double-这是逗号后要显示的位置的定义-看看如何在google中通过printf()方法显示double/float:)编译器没有警告您关于%f
-int不匹配的问题吗?试着自己调查一下。。比如说,[%f]、5.0][%f]、.5][“%.5f”、5][“%.5f”、5.0]零扩展不会发生在通用IA-32 ABI上(32位被推送,64位被读取,没有零扩展),也不会发生在通用的x86-64 ABI上(第一个浮点参数是从xmm0
获得的),所以我不确定您的观点是什么。
#include <stdio.h>
int main()
{
printf("%f",5);
}
#include <stdio.h>
int main()
{
printf("%f", 5.0);
}
5.000000