看起来可能已经存在(至少在C99中)长度修饰符可以应用于int
:%hhd
,%hd
,%ld
和%lld
表示signed char
,short
,long
和long long
。甚至还有适用于double
的长度修饰符:%Lf
表示long double
。
问题是为什么他们忽略了float
?遵循该模式,它可能是%hf
。
答案 0 :(得分:47)
因为在C变量函数调用中,任何float
参数都被提升(即转换)为double
,因此printf
获得double
并使用{{ 1}}让它在其实现中。
过去(C89和K& R C),每个va_arg(arglist, double)
参数都转换为float
。当前标准省略了针对具有明确原型的固定arity函数的此促销。它与ABI&有关(并详细说明)。 calling conventions实施。实际上,当作为参数传递时,double
值通常会被加载到双浮点寄存器中,但细节可能会有所不同。以Linux x86-64 ABI specification为例。
此外,没有实际的理由为float
提供特定的格式控制字符串,因为您可以根据需要调整输出的宽度(例如,使用float
),%8.5f
在%hd
中比在scanf
除此之外,我想原因(省略printf
指定%hf
- 在调用者float
中促进double
是历史性的:首先,C是一种系统编程语言,而不是HPC语言(Fortran在HPC中是首选,直到20世纪90年代后期)并且printf
不是很重要;它(并且仍然)被认为是float
,一种降低内存消耗的方法。今天的FPU足够快(在台式机或服务器计算机上)以避免使用short
,除非作为使用更少内存的手段。你基本上应该相信每个float
都在某个地方(可能在 FPU或CPU中)转换为float
。
实际上,您的问题可能会被解释为:为double
存在%hd
的原因(它基本上没用,因为printf
在您通过printf
时会获得int
一些short
;但是scanf
需要它!)。我不知道为什么,但我想,比系统编程更有用。
您可以花时间游说下一个ISO C标准,%hf
为printf
接受float
double
(printf
short
来电{}} int
- s被提升为float
),当双精度值超出%hf
- s的范围时,未定义的行为,以及{{1}接受的对称scanf
对于float
指针。祝你好运。
答案 1 :(得分:2)
考虑到scanf
有浮动,双重或双倍的单独格式说明符,我不明白为什么printf
和类似的功能没有以类似的方式实现,但是这就是C / C ++和标准的结果。
根据处理器和当前模式,推送或弹出操作的最小大小可能存在问题,但这可能是使用默认填充处理的,类似于局部变量或结构中的变量的默认对齐。当它从16位编译到32/64位编译器时,微软放弃了对80位(10字节)long double
的支持,现在将long double
与double
s相同(64位/ 8字节)。他们可以根据需要将它们填充到12或16字节边界,但这还没有完成。
答案 2 :(得分:2)
当C被发明时,所有浮点值在用于计算或传递给函数(包括)double
之前都被转换为公共类型(即printf
),因此没有必要for printf
在浮点类型之间做出任何区分。
为了提高算术效率和准确性,IEEE-754浮点标准定义了一个80位类型,它比普通的64位double
大,但可以更快地处理。意图是给定像a=b+c+d;
这样的表达式,将所有内容转换为80位类型,将三个80位数字相加,并将结果转换为64位类型,将更快更准确而不是将总和(b+c)
计算为64位类型,然后将其添加到d
。
为了支持新类型,ANSI C定义了一种新类型long double
,其实现可以引用新的80位类型或64位double
。不幸的是,即使IEEE-754 80位类型的目的要使所有值按照它们被提升为double
的方式自动升级到新类型,ANSI也是如此新类型传递给printf
或其他可变方法与其他浮点类型不同,从而使这种自动提升无法维持。
因此,创建C时存在的两种浮点类型都可以使用相同的%f
格式说明符,但之后创建的long double
需要不同的%Lf
格式说明符(使用大写 L
)。
答案 3 :(得分:2)
%hhd
,%hd
,%ld
和%lld
已添加到printf
,以使格式字符串与scanf
更加一致,即使由于默认参数促销,它们对于printf
来说是多余的。
那么为什么%hf
没有添加float
?这很简单:查看scanf
的行为,float
已经有了格式说明符。它是%f
。 double
的格式说明符为%lf
。
%lf
正是C99添加到printf
的内容。在C99之前,%lf
的行为未定义(通过省略标准中的任何定义)。从C99开始,它是%f
的同义词。