簡體   English   中英

printf()是否依賴於格式說明符的順序?

[英]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彈出第二個double0x00000000一半,所以它似乎工作。

當您在printf格式字符串中說%d時, 必須傳遞一個int值作為相應的參數。 否則行為是未定義的 ,這意味着您的計算機可能會崩潰或外星人可能會敲門。 類似於%fdouble

是。 參數從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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM