【问题标题】:C printf using %d and %fC printf 使用 %d 和 %f
【发布时间】:2011-01-17 11:25:21
【问题描述】:

我正在研究这个程序,我注意到将 %f 用于 double 并将 %d 用于 float 给我带来了完全不同的东西。有人知道为什么会这样吗?

int main ()
{
 float a = 1F;
 double b = 1;

 printf("float =%d\ndouble= %f", a, b);
}

这是输出

float = -1610612736
double = 190359837192766135921612671364749893774625551025007120912096639276776057269784974988808792093423962875123204096.0000

【问题讨论】:

  • 请参阅§7.21.6.1 The printf function 的 C11 规范(或 fprintf() 的 POSIX 规范)以获取有关如何正确使用 printf() 的信息以及 §6.5.2.2 Function calls ¶6 and 7 有关浮点参数传递方式的信息可变参数函数。现代 C 编译器(如 GCC 和 Clang)很容易为格式不匹配提供广泛的诊断——您应该启用编译警告。

标签: c printing floating-point double printf


【解决方案1】:

%d 打印一个整数,因此您的 printf 将您的变量 a 解释为 int。

在 gcc 3.4.6 中,我的代码的两个值都为 0(在从 a 初始化中取出 F 之后,因为这会导致编译器错误)。我怀疑这与被解释为 int 为 0 的 a 变量的一部分有关,然后编译器会感到困惑......(可能有更好的解释,但我想不出)。

对两个变量使用 %f 为我打印两个变量的 1.000000。

您可以在此页面底部附近找到转换字符列表:

http://www.exforsys.com/tutorials/c-language/managing-input-and-output-operations-in-c.html

【讨论】:

  • F 相关的编译器错误是因为它不能附加到整数(例如,1.0F 很好)。
【解决方案2】:

%d 代表十进制,它需要int 类型的参数(或一些较小的有符号整数类型,然后被提升)。浮点类型floatdouble 都以相同的方式传递(升级为double)并且它们都使用%f。在 C99 中,您还可以使用 %lf 来表示较大的 double,但这纯粹是为了装饰(请注意,scanf 不会发生提升,这实际上会有所不同)。

【讨论】:

  • 嗯,这是真的codepad.org/labE8lgy,但我确实想知道它实际上是如何工作的......
【解决方案3】:

由于变量参数的工作方式,除了%d%f 之外,C 不知道您实际传递给它的值的类型。当你传入一个变量参数时,你基本上是在做(void*)&myvalue,因为编译器和运行时的函数都不能确定变量的类型,除了格式化字符串中给出的内容。因此,即使有可用的隐式转换,编译器也不知道需要它。

好吧,在大多数系统上,double 是 8 个字节,而 float 是 4 个字节。所以这两种类型不是二进制兼容的。这就像试图将字符串解释为 double 或其他不兼容的类型。

【讨论】:

  • 正确,但这并不是关于floatdouble 之间的兼容性。实际上,float 类型的可变参数在传递之前总是被提升为double,这意味着float 类型在这里不涉及任何事情。传递给printf 的两个值都具有double 类型。第一个内部被解释为int(因为%d 说明符)。 intdouble 之间的不兼容是导致观察到的未定义行为的原因。
  • 使用诸如printf() 之类的可变参数函数时,作为变量参数列表的一部分传递的任何float 值都会自动转换为double(参见C11 §6.5.2.2 Function calls ¶6 & 7)。
  • 我真的不能同意“你基本上是在做(void *)&myvalue”——这些值是作为值传递的,而不是作为指针传递的。
【解决方案4】:

它与数据的内部表示有关。您正在尝试打印一个浮点数,就好像它是一个 int,它具有完全不同的内部(二进制)表示。

double 情况类似。您可能在浮点变量之后有垃圾(任何数据)。该垃圾被解释为双精度值的一部分。

【讨论】:

    猜你喜欢
    • 2019-08-14
    • 2017-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-28
    • 2021-12-13
    • 2013-06-24
    • 1970-01-01
    相关资源
    最近更新 更多