Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
关于C中的转换说明符_C_Format Specifiers - Fatal编程技术网

关于C中的转换说明符

关于C中的转换说明符,c,format-specifiers,C,Format Specifiers,我对C中的转换说明符有一个问题 在第五句中,如果我使用%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("

我对C中的转换说明符有一个问题

在第五句中,如果我使用
%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);
}
#包括
内部主(空)
{
长双数;
printf(“值:”);
scanf(“%f”,&num);//如果使用%lf或%lf而不是%f,则不会发生错误。
printf(“值:%f\n”,num);
}

%f
用于读取
浮点
s,而不是
双精度
s或
长双精度
s

%lf
用于读取
double
s

%Lf
用于读取
long double
s


如果您的程序在变量类型为长双精度时使用
%lf
,这只是巧合。这可能是因为
sizeof(double)
与平台上的
sizeof(long double)
相同。理论上,这是一种未定义的行为。

%f
用于读取
浮点
s,而不是
双精度
s或
长双精度
s

%lf
用于读取
double
s

%Lf
用于读取
long double
s


如果您的程序在变量类型为长双精度时使用
%lf
,这只是巧合。这可能是因为
sizeof(double)
与平台上的
sizeof(long double)
相同。理论上,这是未定义的行为。

在查看FreeBSD系统(顺便说一句,它是POSIX)上的
printf(3)
手册页时,我得到以下信息:

以下长度修饰符适用于
a
a
e
e
f
f
g
, 或
G
转换:

     Modifier    a, A, e, E, f, F, g, G
     l (ell)     double (ignored, same behavior as without it)
     L           long double
我使用了32位浮点数据类型的转换。但这里的问题是,原因是不同的浮点格式有不同的大小,而
printf
函数需要知道它是哪种格式,以便能够正确地进行转换。在浮点上使用
%Lf
可能会导致分段错误,因为转换正在访问变量外部的数据,因此会出现未定义的行为

  • 浮点:32位
  • 双精度:64位
  • 长双:80位
现在对于长双精度,实际大小由平台和实现定义。80位是10个字节,但这并不完全适合没有填充的32位对齐方式。因此,大多数实现使用96位或128位(分别为12字节或16字节)来设置对齐


不过这里要小心,因为它可能需要128位,但这并不意味着它是一个
\uuu128
(如果使用gcc或clang)。至少有一个平台指定
long double
确实意味着
\uuu float128
(我认为是SunOS),但它是在软件中实现的,速度很慢。此外,有些编译器(微软和英特尔会想到)
long double
=
double
,除非您在命令行上指定一个开关。

在FreeBSD系统(顺便说一句,是POSIX)上查看
printf(3)
的手册页时,我得到以下信息:

以下长度修饰符适用于
a
a
e
e
f
f
g
, 或
G
转换:

     Modifier    a, A, e, E, f, F, g, G
     l (ell)     double (ignored, same behavior as without it)
     L           long double
我使用了32位浮点数据类型的转换。但这里的问题是,原因是不同的浮点格式有不同的大小,而
printf
函数需要知道它是哪种格式,以便能够正确地进行转换。在浮点上使用
%Lf
可能会导致分段错误,因为转换正在访问变量外部的数据,因此会出现未定义的行为

  • 浮点:32位
  • 双精度:64位
  • 长双:80位
现在对于长双精度,实际大小由平台和实现定义。80位是10个字节,但这并不完全适合没有填充的32位对齐方式。因此,大多数实现使用96位或128位(分别为12字节或16字节)来设置对齐


不过这里要小心,因为它可能需要128位,但这并不意味着它是一个
\uuu128
(如果使用gcc或clang)。至少有一个平台指定
long double
确实意味着
\uuu float128
(我认为是SunOS),但它是在软件中实现的,速度很慢。此外,有些编译器(Microsoft和Intel会想到)
long double
=
double
,除非您在命令行上指定了一个开关。

所以您会问,如果使用了错误的说明符,为什么会收到编译器警告?请后退一步,再次阅读您的问题。然后,拿一本C书,从第一页开始学习。@Olaf这实际上是一个令人困惑的学习主题,因为
%f
指的是
printf
vs
scanf
@dasblinkenlight:中的不同之处,在我自己的函数中,它可能意味着更大的不同。无论如何,这是关于长双精度的,没有区别
printf
acception
double
for
%f
只是一个遗留问题,因为您无法将
float
参数传递给可变函数。在我看来,这是直截了当的。在两个函数中(
logn double
已清除),只要对
float
参数使用
%f
,对
double
参数使用
%lf
即可。对我来说这听起来不是很混乱。所以你问如果你使用了错误的说明符为什么会得到编译器警告?请后退一步,再次阅读您的问题。然后拿一本C语言书,从第一页开始学习。@Olaf T