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&(p_functor));
const data_t x=(*static_cast&(lhs)),
y=(*static_cast&(rhs));
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?
學習編程感覺吃力怎麼辦?
為什麼你需要知道介面的基本原理

TAG:編程 | C編程語言 |