我对C中的转换说明符有疑问。
如果我使用%lf
或%Lf
代替%f
,则在第5句中,不会发生错误。但是,如果我使用%f
,为什么会发生错误?
#include <stdio.h>
int main(void)
{
long double num;
printf("value: ");
scanf("%f",&num); // If I use %lf or %Lf instead of %f, no error occurs.
printf("value: %f \n",num);
}
答案 0 :(得分:6)
%f
旨在用于阅读float
,而不是double
或long double
。
%lf
旨在用于阅读double
s。
%Lf
旨在用于阅读long double
s。
如果您的程序在变量类型为%lf
时与long double
一起使用,则只是巧合。它的工作原理可能是因为sizeof(double)
与您平台上的sizeof(long double)
相同。从理论上讲,这是不确定的行为。
答案 1 :(得分:0)
在FreeBSD系统(顺便提一下是POSIX)上查看printf(3)
的手册页时,我得到以下内容:
以下长度修饰符适用于
a
,A
,e
,E
,f
,F
,{{1 }}, 或g
转化:G
我使用了32位浮点数据类型的转换。但问题在于,原因是因为不同的浮点格式具有不同的大小, Modifier a, A, e, E, f, F, g, G
l (ell) double (ignored, same behavior as without it)
L long double
函数需要知道它是哪一个,以便它可以正确地进行转换。在浮点数上使用printf
可能会导致分段错误,因为转换正在访问变量外部的数据,因此您会得到未定义的行为。
现在对于%Lf
,实际大小由平台和实现定义。 80位是10个字节,但是没有填充,它不能完全适合32位对齐。因此,大多数实现使用96位或128位(分别为12个字节或16个字节)来设置对齐。
这里要小心,因为它可能需要128位并不意味着它是long double
(如果使用gcc或clang)。至少有一个平台指定__float128
表示long double
(我认为是SunOS),但它是用软件实现的,速度很慢。此外,一些编译器(Microsoft和Intel会想到)__float128
= long double
,除非您在命令行上指定了一个开关。