2

我对来自 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')。

4

5 回答 5

4

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

因为float被提升为doubleC 标准中指定的

6.5.2.2 函数调用

[#6] ... float 类型的参数被提升为 double。这些称为默认参数提升。

[#7] ... 函数原型声明器中的省略号符号导致参数类型转换在最后一个声明的参数之后停止。默认参数提升是在尾随参数上执行的。

于 2013-09-27T12:20:34.933 回答
3

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

于 2013-09-27T11:06:33.020 回答
3

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

于 2013-09-27T12:14:28.943 回答
1

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


检查原型scanf()

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

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

char,short晋升为int太。

C11 6.5.2.2 6

“ ...对每个参数执行整数提升,具有浮点类型的参数提升为双精度。这些称为默认参数提升。...”

于 2013-09-27T14:29:00.733 回答
1

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

你可以把它改成

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

它会工作得很好

于 2014-08-18T08:04:27.020 回答