在這種情況下,你應該寫下列之一:
char str1[10] = "%any";
char str1[] = "%any"; // str1 has size 5
const char *str1 = "%any"; // str1 points to a string literal
在格式化字符串%a
是一個十六進制浮點格式。除了沒有提供double
參數(導致未定義的行爲)之外,這可能會寫入超過10個字節,因此會超出緩衝區str1
(導致未定義的行爲)。
這就是爲什麼你看到0x0.07fff00000001p-1022ny
,這是一個十六進制浮點值0x0.07fff00000001p-1022
其次是ny
。也許你得到的非法指令錯誤是因爲你砸碎了堆棧中存儲的返回地址,所以當你的函數返回時,它跳轉到一個無效的地址。
作爲一個經驗法則,如果您使用printf
函數之一,並且在格式字符串之後沒有指定至少一個可變參數,那麼您很可能會做錯某些事情。 f
在printf
中的含義是該函數的格式爲,但是當您沒有任何要格式化的內容時您正在使用它。所以這只是一個字符串副本,有一個額外的機會讓它錯誤。
如果你想使用printf
系列函數的一個寫一個字符串,那麼你就可以避免意外指定的格式,你不是那個意思是這樣的:
sprintf(str1, "%s", SOME_STRING);
,或者利用長 - 檢查:
#define STR1_SIZE 10
char str1[STR1_SIZE];
if (snprintf(str1, STR1_SIZE, "%s", SOME_STRING) >= STR1_SIZE) {
// error-handling here
}
假如你不小心知道SOME_STRING
適合你的緩衝區,那麼你可以省略錯誤處理和/或使用strcpy
代替。但是當你這樣做的時候你看起來很愚蠢,而且長度錯了。
您還可以使用sizeof(str1)
代替STR1_SIZE
提供str1
是一個數組(因爲它是在這裏),而不是一個指針(因爲它是在大多數字符串處理代碼)。
我試過轉義,即在sprintf中使用「\%any」而不是「%any」;但這並沒有幫助。
不錯的嘗試,沒有雪茄;-)
反斜線在一個字符串逃避特殊字符。由於%
並不意味着字符串文字中的任何特殊內容,因此轉義它不起作用。由此產生的字符串是五個字符%
,a
,n
,y
,\0
。
稍後,您將該字符串傳遞給sprintf
。 現在%
有特殊含義,並有不同的轉義方式:%%
。
在'printf()'的每一個不錯的文檔中都記錄了'%'的轉義。爲什麼不只閱讀其中一份文件? – 2012-11-08 14:43:56
不應該關閉太本地化......問如何轉義'%'根本不是本地化的。 – djechlin
@djechlin沒有閱讀文檔使其過於本地化(對於那些不閱讀文檔的人)。 – 2012-11-08 18:20:35