关于 C 中的转换说明符
About conversion specifier in C
我对 C 中的转换说明符有疑问。
在第 5 句中,如果我使用 %lf
或 %Lf
而不是 %f
,则不会出现错误。但是为什么我用%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);
}
%f
用于读取 float
s,而不是 double
s 或 long double
s。
%lf
用于阅读 double
s.
%Lf
用于阅读 long double
s.
如果您的程序在变量类型为long double
时使用%lf
,那只是巧合。它起作用可能是因为 sizeof(double)
与您平台上的 sizeof(long double)
相同。理论上是未定义的行为。
在 FreeBSD 系统(顺便说一句,POSIX)上查看 printf(3)
的手册页时,我得到以下信息:
The following length modifier is valid for the a
, A
, e
, E
, f
, F
, g
,
or G
conversion:
Modifier a, A, e, E, f, F, g, G
l (ell) double (ignored, same behavior as without it)
L long double
我使用了 32 位浮点数据类型的转换。但这里的问题是,原因是因为不同的 float 格式具有不同的大小,并且 printf
函数需要知道它是哪一种,以便它可以正确地进行转换。在浮点数上使用 %Lf
可能会导致分段错误,因为转换正在访问变量外部的数据,因此您会得到未定义的行为。
- 浮动:32 位
- 双:64 位
- 长双精度:80 位
现在 long double
,实际大小由平台和实现定义。 80 位是 10 个字节,但这并不完全适合没有填充的 32 位对齐。因此大多数实现使用 96 位或 128 位(分别为 12 字节或 16 字节)来设置对齐方式。
这里要小心,仅仅因为它可能需要 128 位并不意味着它是 __float128
(如果使用 gcc 或 clang)。至少有一个平台指定 long double
确实意味着 __float128
(我认为是 SunOS),但它是在软件中实现的,速度很慢。此外,某些编译器(想到 Microsoft 和 Intel)long double
= double
除非您在命令行上指定开关。
我对 C 中的转换说明符有疑问。
在第 5 句中,如果我使用 %lf
或 %Lf
而不是 %f
,则不会出现错误。但是为什么我用%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);
}
%f
用于读取 float
s,而不是 double
s 或 long double
s。
%lf
用于阅读 double
s.
%Lf
用于阅读 long double
s.
如果您的程序在变量类型为long double
时使用%lf
,那只是巧合。它起作用可能是因为 sizeof(double)
与您平台上的 sizeof(long double)
相同。理论上是未定义的行为。
在 FreeBSD 系统(顺便说一句,POSIX)上查看 printf(3)
的手册页时,我得到以下信息:
The following length modifier is valid for the
a
,A
,e
,E
,f
,F
,g
, orG
conversion:Modifier a, A, e, E, f, F, g, G l (ell) double (ignored, same behavior as without it) L long double
我使用了 32 位浮点数据类型的转换。但这里的问题是,原因是因为不同的 float 格式具有不同的大小,并且 printf
函数需要知道它是哪一种,以便它可以正确地进行转换。在浮点数上使用 %Lf
可能会导致分段错误,因为转换正在访问变量外部的数据,因此您会得到未定义的行为。
- 浮动:32 位
- 双:64 位
- 长双精度:80 位
现在 long double
,实际大小由平台和实现定义。 80 位是 10 个字节,但这并不完全适合没有填充的 32 位对齐。因此大多数实现使用 96 位或 128 位(分别为 12 字节或 16 字节)来设置对齐方式。
这里要小心,仅仅因为它可能需要 128 位并不意味着它是 __float128
(如果使用 gcc 或 clang)。至少有一个平台指定 long double
确实意味着 __float128
(我认为是 SunOS),但它是在软件中实现的,速度很慢。此外,某些编译器(想到 Microsoft 和 Intel)long double
= double
除非您在命令行上指定开关。