2012-07-10 27 views
5

可能重複:
warning: format not a string literal and no format arguments爲什麼的printf(的char [])生成一個警告,同時的printf( 「ASDF」)不

我有很簡單的問題:爲什麼當我發char[] s = "hi"; printf(s)它發出警告:「警告:格式不是字符串文字和格式參數」,同時printf("aa")不會。

我已經讀過字符數組和字符串文字(一個是const char const*,另一個是char*)之間的差異,但是從printf()簽名:

http://www.gnu.org/software/libc/manual/html_node/Formatted-Output-Functions.html#Formatted-Output-Functions

我看到它是適用於任何的那類型。所以我的問題是爲什麼printf("aaa")不發出任何警告(它是否以某種方式檢查文字是一個常量,而陣列不是)?

+0

FWIW,VC++不會抱怨非常量文字。 – Mysticial 2012-07-10 15:08:32

+0

哪個編譯器對您的代碼執行此操作? – Jay 2012-07-10 15:10:22

+0

@Mystical,我同意。 VC不會抱怨。想知道爲什麼其他編譯器complians或爲什麼VC不? – Jay 2012-07-10 15:11:27

回答

6

的GNU編譯器和大量其他編譯器的這些日子確實檢查格式字符串爲printf - 家庭對所提供的參數。編譯器警告它不能對非文字字符串執行此操作。

使用非文字格式的字符串被認爲是不好的做法。使用你不能控制的格式字符串要糟得多。

+0

如果我正確理解你,你說的是因爲字符串文字被複制到數組中,編譯器不知道該數組在編譯時包含的內容,因此它不能檢查它的內容是否是一個好的格式字符串以及提供的參數。 – dhblah 2012-07-10 15:22:58

+0

但爲什麼然後'const char * s =「hi」; printf(s)'也會產生警告? – dhblah 2012-07-10 15:24:39

+0

哦,我發現它'const char const * s =「hi」; printf(s)'不會產生任何錯誤。所以'const char const *'似乎是一個字符串文字的類型。 – dhblah 2012-07-10 15:26:35

1

我在第二種情況下賭編譯器看到該字符串中沒有任何格式,因此不會有危險:

/* "aa" is not dangerous, so do not display a warning */ 
printf("aa") 

在第一種情況下,編譯器可能無法看到格式字符串的值,因此它無法驗證它:

/* the compiler doesn't know the content of the memory region pointed by `s`, so 
    he can't determine if it's dangerous or not. Then display a warning */ 
printf(s) 
1

免責聲明:我不知道這是原因警告,但它是一個原因

由於參數prinrf數量取決於轉換說明的數目,它是高度不常見使用一個字符串作爲格式字符串(即,有可能的一個錯誤)。此外,如果格式字符串不是文字,它確實來自其他地方 - 例如用戶或文件輸入。在這種情況下,錯誤(或惡意)輸入可能會導致程序崩潰,或者更糟糕的是,會注入代碼(即安全漏洞)。在任何情況下,如果你想打印的東西不是文字,也沒有格式參數,你很可能會尋找puts,而不是printf。 (恕我直言,puts是在C庫中的最未充分利用的功能。你有曾經看到一個「你好,世界」使用它嗎?)

+0

我讀過一些關於'puts'的文章。 – dhblah 2012-07-10 15:15:16

4

這樣做的原因是,有一堆的安全問題約10 -15年前,人們認爲可以安全地調用printf(s),其中「s」具有用戶提供的輸入。許多編譯器爲此避免了這些問題。如果您只想打印出一個字符串,請使用puts()。如果你不確定你發送到printf的字符串不包含'%'字符,你應該使用printf(「%s」,s);

相關問題