我有一个关于来自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 *”类型(指向float的指针)。令我感到困扰的是,gcc认为第二个参数的类型为'double',而实际上它的类型为'float'。
这引出了我的问题,为什么gcc认为scanf的第二个参数是double,当它实际上是一个浮点数时?
我已就此主题进行了一些研究以获得答案,但我找到的每个答案都是关于如何摆脱警告(写'&amp; number'而不是'number')。
答案 0 :(得分:4)
这引出了我的问题,为什么gcc相信第二个论点 当scanf实际上是浮点数时,scanf是double吗?
因为{C}标准
中指定的float
被提升为double
6.5.2.2函数调用
[#6] ......论点 具有float类型的提升为double。这些是 称为默认参数促销。
[#7] ...函数原型中的省略号表示法 声明器导致参数类型转换后停止 最后声明的参数。默认参数促销 在尾随参数上执行。
答案 1 :(得分:3)
你已经知道你将错误的东西(如评论中所述)传递给scanf
所以只是告诉你警告背后的原因是你提供的float
参数首先被提升为double
}。
答案 2 :(得分:3)
您的编译器是正确的,传递给scanf
的参数确实是double
:对于参数列表的...
部分,执行一组默认转换。特别是所有float
参数都会提升为double
,这就是scanf
可以看到的内容。
答案 3 :(得分:1)
[编辑]除了发布scanf()
原型之外,我现在看到答案回应@chill。
“模仿是最真诚的奉承形式。”
检查原型scanf()
int scanf(const char * restrict format, ...);
...
表示允许任意数量的任何类型的参数。由于历史原因,当传递给这些函数时,较小而不是double
的所有FP参数都会被提升为double
。这就是编译器将其称为double
。
char
,short
也会提升为int
。
C11 6.5.2.2 6
“...对每个参数执行整数提升,并对其进行参数化 将float类型提升为double。这些被称为默认参数 促销活动。 ......“
答案 4 :(得分:1)
该错误消息具有误导性,scanf期望变量的地址将数据填充回它并且您传递了一个值,并且当scanf查找该地址时发现它与形成“%f”时建议的不同“
您可以将其更改为
scanf("%f", &number); // &number instead of number
它会正常工作