2012-01-17 73 views
2
int main() 
{ 
    int x,y; 
    int z; 
    char s='a'; 
    x=10;y=4; 
    z = x/y; 
    printf("%d\n",s); //97 
    printf("%f",z); //some odd sequence 
    return 0; 

} 

在上述代碼中,由於控件字符串中的int類型,char s在打印時自動轉換爲int,但在第二種情況下,不會發生int轉換爲float的轉換。爲什麼這樣?在c中的類型轉換

回答

7

在這兩種情況下,第二個參數都被提升爲int。這是可變參數函數的工作方式,與格式字符串無關。

編譯器甚至沒有查看格式字符串:它只是某個函數的參數。那麼,一個真正有用的編譯器可能知道printf()可能看格式字符串,但只是爲了警告你可能犯的錯誤。事實上,gcc做到了這一點:

t.c:9: warning: format ‘%f’ expects type ‘double’, but argument 2 has type ‘int’ 

這是最終責任確保可變參數的格式字符串相匹配。由於在第二個printf()調用中他們沒有,代碼的行爲是未定義的。

0

char不是由於控制字符串而被提升爲intchar作爲int工作,因爲所有傳遞到printf的小於4字節的數據由於可變參數函數的cdecl調用約定而被碰撞到4字節,這是int的大小(這點是以便接下來的數據將在堆棧上的一個4字節邊界上對齊)。

printf不是類型安全的,也不知道你真正傳遞了哪些數據;它會盲目地讀取控制字符串,並根據找到的序列從堆棧中提取一定數量的字節,並將該字節集解釋爲與控制序列對應的數據類型。它不會執行任何轉換,並且您得到某些較爲粗糙的打印輸出的原因是因爲int的位被解釋爲float的位。

+0

難道'printf'從浮點寄存器中爲'%f'指定符獲取參數嗎?無關:你輸錯了'怪異'。 – 2012-01-17 15:25:43

+0

@DanielFischer不,浮點值也傳遞到棧上。您可以通過查看'va_arg'宏的源代碼來看到這一點。 – 2012-01-17 15:27:48

0

由於在控制字符串

int類型即不正確。它正在被轉換,因爲更短的int類型被var_args進程提升爲int。 Int類型不會轉換爲浮點類型,因爲va /預處理器不知道預期的格式。

3

具有可變參數個數的函數遵循默認參數提升的規則。整型促銷規則適用於整數類型的參數,並且float參數轉換爲double

printf("%d\n",s); 

s是炭和被轉換爲int

printf("%f",z); 

z已經是一個int所以在z

執行任何轉換現在轉換說明f需要一個double但對象的默認參數推廣後的類型爲int所以它是未定義的行爲。

這裏是什麼C說與論據

(C99,7.4.1p1)「如果一個參數的函數[...] A型(後晉升可變數量的庫函數的參數)不具有可變數量的參數的函數,行爲是未定義的。「