printf%f如何在32位浮点数上运行

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了printf%f如何在32位浮点数上运行相关的知识,希望对你有一定的参考价值。

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

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

但是floatdouble可能不是这种情况,因为浮点格式不能像这样互换。如果没有将(相当复杂的)转换为其他格式,您根本无法将浮点值打印为double。通过类型惩罚尝试这样做只会打印垃圾。

最重要的是,printf是可变的。编译器在编译时不一定知道将使用什么格式说明符,只知道参数的类型。因此,我唯一可以推测的是,传递给可变函数的所有float值都将无条件地升级为double。但令人难以置信的是,我本可以在C语言编程这么长时间而且不知道这一点。

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

资源:

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

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

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

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

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

  long long *ip = (long long *)&i[0];
  printf("value of i: %lld
", *ip);
  printf("sizeof of i: %lu
", 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.
答案

Variadic argumentsDefault argument promotions

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

.

整数类型的每个参数都经历整数提升(见下文),float类型的每个参数都隐式转换为double类型。

另一答案

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

是的 - 这是完全正确的。

从C标准;

6.5.2.2.7函数原型声明符中的省略号表示法导致参数类型转换在最后声明的参数之后停止。默认参数提升是在尾随参数上执行的。

而“默认参数促销”规则将float推广到double,相关部分是:

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

以上是关于printf%f如何在32位浮点数上运行的主要内容,如果未能解决你的问题,请参考以下文章

C语言中如何保留一位小数点

为什么printf(“%f”,0);给出未定义的行为?

c语言如何控制小数位数?

第六课 实型(浮点型)

如何让 printf 在 STM32F103 上工作?

实验二