【问题标题】:gcc scanf warning believes float is doublegcc scanf 警告认为 float 是双倍的
【发布时间】:2013-09-27 10:57:14
【问题描述】:

我对来自 gcc 编译器的警告消息有疑问。当 scanf 的参数不是指向应该携带用户输入的变量的指针时,会出现警告消息。

#include <stdio.h>

int main(int argc, const char *argv[]) {
    float number;
    scanf("%f", number); /* the value of 'number' is passed, instead of the adress to it */
    return 0;
}

gcc 在编译程序时会给出如下警告信息。

scanf-problem.c: In function 'main':
scanf-problem.c:5:5: warning: format '%f' expects argument of type 'float *', but argument 2 has type 'double' [-Wformat=]
     scanf("%f", number);
     ^

正如预期的那样,gcc 希望 scanf 的第二个参数具有“float *”类型(指向浮点数的指针)。困扰我的是 gcc 认为第二个参数的类型是“double”,而实际上它的类型是“float”。

这让我想到了一个问题,为什么 gcc 认为 scanf 的第二个参数是双精度的,而它实际上是一个浮点数?

我已经对此主题进行了一些研究以获得答案,但我找到的每个答案都是关于如何摆脱警告(写“&number”而不是“number”)。

【问题讨论】:

  • 它基本上是scanf接受地址,如float *,并且您传递了8字节的数字,您是在64位PC上吗?
  • 这解释了很多。事实上,我使用的是 64 位 PC。

标签: c gcc compiler-warnings scanf


【解决方案1】:

这让我想到了这个问题,为什么 gcc 相信第二个论点 的 scanf 是双精度,当它实际上是一个浮点数?

因为 float 按照 C 标准的规定提升为 double

6.5.2.2 函数调用

[#6] ... 参数 具有浮点类型的被提升为双精度。这些是 称为默认参数promotions。

[#7] ... 函数原型中的省略号 声明符导致参数类型转换在 最后声明的参数。默认参数提升 对尾随参数执行。

【讨论】:

    【解决方案2】:

    您已经知道您将错误的东西(如评论中所述)传递给 scanf 因此,只需告知您警告背后的原因,您提供的 float 参数首先会提升为 double

    【讨论】:

      【解决方案3】:

      您的编译器是正确的,传递给scanf 的参数确实是double:对于参数列表的... 部分,执行了一组默认转换。特别是所有float 参数都被提升为double,这是scanf 可以看到的。

      【讨论】:

        【解决方案4】:

        [编辑] 除了发布scanf() 原型之外,我现在看到答案与@chill 相呼应。
        “模仿是最真诚的奉承。”


        检查scanf()的原型

        int scanf(const char * restrict format, ...);
        

        ... 表示允许任意数量的任意类型的参数。由于历史原因,所有小于double 的FP 参数在传递给此类函数时都会提升为double。这就是为什么编译器称它为double

        charshort 也被提升为int

        C11 6.5.2.2 6

        " ...对每个参数执行整数提升,并且参数 具有 float 类型的提升为 double。这些被称为默认参数 促销。 ……”

        【讨论】:

          【解决方案5】:

          错误消息具有误导性,scanf 期望变量的地址将数据填充回它并且您传递了一个值,并且当 scanf 查找该地址时,它发现它与格式化“%f”中建议的不同"

          你可以改成

          scanf("%f", &number); // &number instead of number
          

          它会正常工作

          【讨论】:

          • 问题不在于如何解决警告信息。我质疑的是为什么 gcc 认为我的 float 在错误打印输出中是 double。
          • 想象它像这样 float a;浮动 * 指针ToA = a; // a 的值而不是 a 的地址 scanf("%f",pointerToA) 现在它将在内存中查找给定的任意索引,但 a 的值可以是任何值
          猜你喜欢
          • 1970-01-01
          • 2016-01-21
          • 1970-01-01
          • 1970-01-01
          • 2011-10-24
          • 2015-09-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多