[英]Does printf() depend on order of format specifiers?
#include<stdio.h>
main()
{
float x=2;
float y=4;
printf("\n%d\n%f",x/y,x/y);
printf("\n%f\n%d",x/y,x/y);
}
輸出:
0
0.000000
0.500000
0
用gcc編譯4.4.3程序退出時出錯,代碼為12
如其他答案所述,這是因為格式字符串與參數類型不匹配。
我猜你在這里使用x86(基於觀察到的結果)。
參數在堆棧上傳遞, x/y
雖然類型為float
,但會作為double
傳遞給varargs函數(由於類型為“promotion”規則)。
int
是32位值, double
是64位值。
在這兩種情況下,您都要傳遞x/y
(= 0.5)兩次。 此值的表示形式為64位double
0x3fe0000000000000
,為0x3fe0000000000000
。 作為一對32位字,它存儲為0x00000000
(最低有效32位),然后是0x3fe00000
(最高有效32位)。 所以printf()
看到的棧上的參數如下所示:
0x3fe00000
0x00000000
0x3fe00000
0x00000000 <-- stack pointer
在兩種情況的第一種情況下, %d
會彈出並打印第一個32位值0x00000000
。 %f
彈出接下來的兩個32位值, 0x3fe00000
(64位double
0x3fe00000
最低有效32位),然后是0x00000000
(最重要)。 得到的64位值0x000000003fe00000
(被解釋為double
)是一個非常小的數字。 (如果將格式字符串中的%f
更改為%g
您將看到它幾乎為0,但不完全相同)。
在第二種情況下, %f
正確彈出第一個double
, %d
彈出第二個double
的0x00000000
一半,所以它似乎工作。
當您在printf格式字符串中說%d
時, 必須傳遞一個int
值作為相應的參數。 否則行為是未定義的 ,這意味着您的計算機可能會崩潰或外星人可能會敲門。 類似於%f
和double
。
是。 參數從vararg列表讀取到printf的順序與讀取格式說明符的順序相同。
這兩個printf
語句都是無效的,因為你正在使用一個期望int的格式說明符,但你只給它一個float double。
你在做什么是不端行為。 你所看到的是巧合; printf
可以寫任何東西。
在給出printf
參數時,您必須匹配確切的類型。 你可以舉例如:
printf("\n%d\n%f", (int)(x/y), x/y);
printf("\n%f\n%d", x/y, (int)(x/y));
這個結果並不奇怪,在第一個%d中你傳遞了一個預期整數的double。
http://en.wikipedia.org/wiki/Format_string_attack
與我的問題有關的東西。 支持馬修的答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.