scanf_s 比起 scanf 添加了什麼?
有什麼變化呢?
scanf_s 和 scanf 幾乎是一樣的,但是 scanf_s 在字元串的讀入上有不同,允許在參數中指定讀入字元串的長度上限,以避免讀入的內容長度超過已有的內存空間的長度。比如,如果我們這樣寫:
char word[10];
scanf("%s",word);
然後運行的時候輸入了一個這樣的字元串:
tooyoungtoosimplesometimesnaive
那麼這麼長的字元串就會全部填在 word 數組裡,超過它的長度,這樣會出偏差的。
為了避免出現這樣的偏差,scanf_s 允許你指定讀入串的長度上限,於是我們改成下面這樣:scanf_s("%s",word,(rsize_t)sizeof word);
這樣輸入過長時就會產生錯誤,執行你之前在 set_constraint_handler_s 中定義的錯誤處理函數(如果你沒有定義的話,系統會給你準備一個,也許是直接忽略,也許是直接停止運行),你的程序就不會在這裡搞出什麼偏差。
而且,如果你傳入的參數有空指針的話,也會產生錯誤,執行你定義的錯誤處理函數。
也就是說,使用 scanf_s 比使用 scanf 要更安全。不過,並不是所有的標準庫都實現了 scanf_s,你可以通過檢測 __STDC_LIB_EXT1__ 是否被 #define 了,檢測標準庫是否支持,然後在代碼最前面加上下面這一行:#define __STDC_WANT_LIB_EXT1__ 1
來開啟標準庫對於 scanf_s 以及其他一些函數的更安全的版本(比如 strcpy_s memset_s 之類的)的支持。
這是 C11 新增的內容。如有錯誤,請指出。
scanf_s 幾乎沒有比 scanf 更加安全,除了空指針的檢測。而且 scanf 本身也能做邊界檢查的。
char buffer[128];
scanf("%127s", buffer); // 安全
scanf_s("%127s", buffer, 128); // 安全
scanf("%s", buffer); // 不安全
scanf_s("%s", buffer, 128); // 安全,當輸入過長時能調用報錯函數
說實話,若最後一條的 128 被寫成過大的數也不安全。
個人看來 _s 系列最大的功能就是調用報錯函數,可能可以簡化一些報錯的流程。(set_constraint_handler_s, constraint_handler_t)有點懷疑 _s 系列的用法是——
別人傳來一個莫名其妙的指針/長度/輸入內容,然後你直接就把它傳到 _s 系列函數里去,不過之前要寫對邊界。接下來等著一個統一的報錯流程就行了。另外 qsort_s 和 bsearch_s 有個 context 參數,疑是讓人把 C++ 的函數對象傳進去的…就像這樣:
extern "C"
int c_style_cmpr(const void *lhs, const void *rhs, void *p_functor){
functor_t functor=(*static_cast&
const data_t x=(*static_cast&
y=(*static_cast&
return functor(y, x) - functor(x, y);
}
// 上面的東西或許會在 C 中被譯成同義內容
// ...
qsort_s(array, num_sort, sizeof(data_t), c_style_cmpr, functor);
……純 C 的話不知有沒有這種習慣,C++ 里這麼做怎麼看都很詭異就是。
安全版本,可以看源碼呀
加一個參數就是規定字元串最大長度。是更安全的函數。c11新標準
但是我很討厭微軟默認開安全檢查使得scanf報4996錯誤。 不需要vs這麼貼心。應該把黑鍋讓程序員背(逃你們呀。naive。。。。純純那麼厲害的人可能不知道么。。他只是想膜
(問過題主純純本人了
他:「這麼簡單的問題我怎麼可能不知道」我:「為什麼不加個諸如兩棲動物的標籤」他:「太明顯了」推薦閱讀:
※關於漢字、亂碼和其他
※人機對戰初體驗:Python實現四子棋遊戲
※GitHub排第一的語言為什麼是js?
※學習編程感覺吃力怎麼辦?
※為什麼你需要知道介面的基本原理