2013-09-27 62 views
2

我有一個關於來自gcc編譯器的警告消息的問題。當scanf的參數不是指向應該攜帶用戶輸入的變量的指針時,會發生警告消息。gcc scanf警告認爲float是雙重的

#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,當它實際上是float?

我已經做了一些關於這個話題的研究來得到答案,但我找到的每個答案都是關於如何擺脫警告(寫'&數字'而不是'數字')。

+3

它基本上是scanf函數接受地址,像浮*,並且已經通過了這8個字節數,你是一個64位的電腦上? – Ishmeet

+0

這解釋了很多。事實上,我在一臺64位電腦上。 – oscfri

回答

4

這使我這個問題,爲什麼海合會認爲,第二個參數scanf函數的 是一個雙,當它實際上是一個浮動?

由於float如C標準

6.5.2.2功能指定被提升爲double調用

[#6] ...具有類型浮動參數 被提升到一倍。這些是 被稱爲默認參數促銷。

[#7] ...函數原型中的省略號表示 聲明符導致參數類型轉換在 上次聲明的參數後停止。在結尾參數上執行默認參數促銷 。

3

你已經知道要傳遞錯誤的東西(如在評論中提及),以scanf所以才通知你身後發出警告的原因是float說法您提供首次晉升爲double

3

您的編譯器是正確的,傳遞給scanf的參數確實是double:對於參數列表的...部分,執行一組默認轉換。特別是所有的float參數都被提升爲double,這就是scanf得到的結果。

1

[編輯]除了發佈scanf()原型,我現在看到答案回聲@chill。 「模仿是奉承的最真誠的形式。「


檢查原型scanf()

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

...意味着任何數量的任何類型的參數都不允許。由於歷史原因,所有FP參數小double被晉升爲double當傳遞給這樣的函數時,爲什麼編譯器稱它爲double

charshort也被提升爲int

C11 6.5.2.2 6

「......整型的提升,在每個參數執行,論點 有float類型都提升一倍。這些被稱爲默認參數 促銷活動......」

1

錯誤消息是誤導性的,scanf希望變量的地址填充數據並返回給它,並且您傳遞了一個值,並且當scanf查找該地址時發現它與在格式化過程中建議的不同之處「 f「

您可以將其更改爲

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

,它會工作得很好

+0

問題不在於如何解決警告信息。我質疑的是,爲什麼gcc認爲我的float在錯誤打印輸出中是雙倍的。 – oscfri

+0

想象一下這樣吧 float a; float * pointerToA = a; //代替 scanf(「%f」,pointerToA)的地址值 現在它會在內存中查找給定的任意索引,但是其值可能是任何值 –