sprintf_s与_snprintf与_snprintf_s
| MSDN頁面分別如下: spirntf_s: http://msdn.microsoft.com/zh-cn/library/ce3zzk1k%28VS.80%29.aspx _snprintf: http://msdn.microsoft.com/zh-cn/library/2ts7cx93%28v=VS.90%29.aspx _snprintf_s: http://msdn.microsoft.com/zh-cn/library/f30dzcf6.aspx 三個頁面都有自己的例子。。其中后2個的例子比較多內容一些。 ? 為免將來頁面失效:int sprintf_s( char *buffer, size_t sizeOfBuffer, const char *format [, argument] ... );template <size_t size> int sprintf_s( char (&buffer)[size], const char *format [, argument] ... ); // C++ onlyint _snprintf( char *buffer, size_t count, const char *format [, argument] ... );int _snprintf( char (&buffer)[size], size_t count, const char *format [, argument] ... ); // C++ onlyint _snprintf_s( char *buffer, size_t sizeOfBuffer, size_t count, const char *format [, argument] ... );int _snprintf_s( char (&buffer)[size], size_t count, const char *format [, argument] ... ); // C++ only ? 呼呼。。內容還挺多。 ? ? 這里比較引人注目的是,_snprintf_s為什么在sizeOfBuffer的基礎上,還要多加一個count? count似乎是用來控制理想的寬度的。 如果得到的字符串超過了count,于是會被截斷到count的長度后面再加一個null-teminate 當然,更高優先級的應該是sizeOfBuffer,必須不超過這個大小。這個就說到點子上了。 ? 如果應該輸出的字符串的大小已經達到了sizeOfBuffer,那么就溢出了。溢出的情況下,sprintf_s函數把這當做一個錯誤,會把buffer緩沖區置為一個空字符串""。 而_snprintf_s的好處就是,有了count參數,輸出的字符串就算超過緩沖區長度,仍然會有輸出,輸出字符串被截斷到count大小,在這個大小的字符串后面加null-teminate。 當然,如果count被設置成和sizeOfBuffer同樣大,或者不合理的更大,那么這個count參數就失去了意義。 這時候,如果輸出字符串將要達到或者超過sizeOfBuffer,一樣導致一個錯誤,輸出緩沖區被置為空字符串。 因此,如果希望緩沖區被盡量利用,可以把count參數置為_TRUNCATE,這樣的情況下,實際上效果相當于是將count設置為sizeOfBuffer - 1。 ? ? 至于C語言環境下,sprintf_s與_snprintf的對比: 注意到,_snprintf的參數用的是count,而sprintf_s的參數用的是sizeOfBuffer。這很能說明問題。 看下對_snprintf的說明: Let len be the length of the formatted data string (not including the terminating null). len and count are in bytes for _snprintf, wide characters for _snwprintf. If len < count, then len characters are stored in buffer, a null-terminator is appended, and len is returned. If len = count, then len characters are stored in buffer, no null-terminator is appended, and len is returned. If len > count, then count characters are stored in buffer, no null-terminator is appended, and a negative value is returned. ? 也就是說,_snprintf的count參數明明白白的就是一個count。 如果輸出字符串剛好達到count,由于期待的最大長度就是count,那么輸出字符串肯定要完整,不能截斷。 但是假如字符串緩沖區的大小其實就是count,這怎么辦?MS VCRT的設計者認為,在這種情況下應該把輸出字符串的長度告知調用者,讓調用者來決定是否自己添加null-teminate。 換句話說,調用_snprintf時要注意了,必須檢查_snprintf的返回值,如果返回值不是正數,那么還得注意你的字符串緩沖區并不是null-teminate結尾的。 ? 總結來說,sprintf_s在緩沖區不夠大時會失敗,失敗時緩沖區中是一個空字符串。 _snprintf不會失敗,但是必須注意如果緩沖區不夠大,緩沖區的內容將不是null-teminate的,必須自己注意字符串的結束。 _snprintf_s結合了2者的優點,只要count參數設置合理,函數就不會因緩沖區不夠而失敗。 ? 但是觀察_snprintf_s的說明,有一個很有趣的內容。 這3族函數中,有失敗情況的2個函數sprintf_s和_snprintf_s中,(再次強調,我這里的失敗的意思是,調用后緩沖區里是一個空字符串),_set_invalid_parameter_handler設置的錯誤處理器,在失敗的情況下會被調用。 ? 而截斷的情況下,錯誤處理器并不會被調用。 ? VC的庫開發者總是提供一些怪怪的東西。無論如何,讓代碼更加安全總是符合大家的總體期望的。 另外補充一下,查閱這些字符串安全函數的資料的時候要注意, 對微軟來說,凡是限制字符串復制長度的函數,這些設計者仍然認為是不安全的,因為邏輯上來說, 這些長度參數只是限制了源字符串被復制的長度,而不是目標緩沖區的長度。 也就是說,微軟的這些設計者認為,安全的方式其實是依賴C++的機制,辨認出目標緩沖區的真正大小,以此實現安全的復制。 | 
轉載于:https://www.cnblogs.com/yangxx-1990/p/4877111.html
總結
以上是生活随笔為你收集整理的sprintf_s与_snprintf与_snprintf_s的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 人民银行支付系统(CNAPS)和中国银联
- 下一篇: int指令01 - 零基础入门学习汇编语
