printf%f如何在32位浮点上工作

时间:2018-12-10 20:02:00

标签: c printf variadic-functions

%f printf格式代码指定为对类型double [source]的值进行操作。但是,一个简单的测试程序演示了它也可以与类型float的值一起使用。如何运作?

具有整数类型(例如intlong long int)的等效情况之所以有效,是因为在小端机器上,一个32位整数的低位字节恰好与低位字节重叠。对64位整数的字节进行排序,因此只要高位为0,您就会得到“正确”的答案。

但是floatdouble不可能如此,因为浮点格式不能像这样互换。您根本无法将浮点值打印为双精度,而不进行(相当复杂的)转换为另一种格式。尝试通过类型合并进行操作只会打印垃圾。

最重要的是,printf是可变的。编译器不一定在编译时就知道将使用哪种格式说明符,仅知道参数的类型。因此,我唯一可以推测的是,传递给可变参数函数的 all float值将无条件地升级为double。但这让我感到困惑,因为我可能已经用C语言编程了这么长时间,却一无所知。

C在这里如何执行隐式强制?

来源:

#include <stdio.h>
#include <math.h>

int main() {
  float x[2] = {M_PI, 0.0};
  printf("value of x: %.16e\n", x[0]);
  printf("size of x: %lu\n", sizeof(x[0]));

  double *xp = (double *)&x[0];
  printf("value of *xp: %.16e\n", *xp);
  printf("size of *xp: %lu\n", sizeof(*xp));

  double y = M_PI;
  printf("value of y: %.16e\n", y);
  printf("size of y: %lu\n", sizeof(y));

  int i[2] = {1234, 0};
  printf("value of i: %lld\n", i[0]);
  printf("sizeof of i: %lu\n", sizeof(i[0]));

  long long *ip = (long long *)&i[0];
  printf("value of i: %lld\n", *ip);
  printf("sizeof of i: %lu\n", sizeof(*ip));

  return 0;
}

输出:

value of x: 3.1415927410125732e+00
size of x: 4
value of *xp: 5.3286462644388174e-315
size of *xp: 8
value of y: 3.1415926535897931e+00
size of y: 8
value of i: 1234
sizeof of i: 4
value of i: 1234
sizeof of i: 8

编译命令和版本:

$ gcc test_float.c -o test_float
$ gcc --version
gcc (Ubuntu 5.5.0-12ubuntu1~16.04) 5.5.0 20171010
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

2 个答案:

答案 0 :(得分:5)

  

因此,我唯一可以推测的是,传递给可变参数函数的所有浮点值将无条件地升级为double。

是的-完全正确。

根据C标准;

  

6.5.2.2.7函数原型声明器中的省略号引起最后一次声明后参数类型转换停止   参数。默认参数提升在尾随执行   争论。

“默认参数提升”规则会将float提升为double,相关部分为:

  

6.5.2.2.6如果表示被调用函数的表达式的类型不包含原型,则整数提升为   对每个参数执行,并且具有float类型的参数是   提升为两倍。

答案 1 :(得分:4)

请参见Variadic argumentsDefault argument promotions

  

在函数调用中,作为变量参数列表一部分的每个参数都经过称为default argument promotions的特殊隐式转换。

  

每个整数类型的参数都会进行整数提升(请参见下文),并且 float类型的每个参数都隐式转换为double类型