sprintf_s与_snprintf与_snprintf_s
| MSDN頁(yè)面分別如下: 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 三個(gè)頁(yè)面都有自己的例子。。其中后2個(gè)的例子比較多內(nèi)容一些。 ? 為免將來(lái)頁(yè)面失效: 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++ only int _snprintf(char *buffer, size_t count, const char *format [, argument] ... ); int _snprintf(char (&buffer)[size], size_t count, const char *format [, argument] ... ); // C++ only int _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 ? 呼呼。。內(nèi)容還挺多。 ? ? 這里比較引人注目的是,_snprintf_s為什么在sizeOfBuffer的基礎(chǔ)上,還要多加一個(gè)count? count似乎是用來(lái)控制理想的寬度的。 如果得到的字符串超過(guò)了count,于是會(huì)被截?cái)嗟絚ount的長(zhǎng)度后面再加一個(gè)null-teminate 當(dāng)然,更高優(yōu)先級(jí)的應(yīng)該是sizeOfBuffer,必須不超過(guò)這個(gè)大小。這個(gè)就說(shuō)到點(diǎn)子上了。 ? 如果應(yīng)該輸出的字符串的大小已經(jīng)達(dá)到了sizeOfBuffer,那么就溢出了。溢出的情況下,sprintf_s函數(shù)把這當(dāng)做一個(gè)錯(cuò)誤,會(huì)把buffer緩沖區(qū)置為一個(gè)空字符串""。 而_snprintf_s的好處就是,有了count參數(shù),輸出的字符串就算超過(guò)緩沖區(qū)長(zhǎng)度,仍然會(huì)有輸出,輸出字符串被截?cái)嗟絚ount大小,在這個(gè)大小的字符串后面加null-teminate。 當(dāng)然,如果count被設(shè)置成和sizeOfBuffer同樣大,或者不合理的更大,那么這個(gè)count參數(shù)就失去了意義。 這時(shí)候,如果輸出字符串將要達(dá)到或者超過(guò)sizeOfBuffer,一樣導(dǎo)致一個(gè)錯(cuò)誤,輸出緩沖區(qū)被置為空字符串。 因此,如果希望緩沖區(qū)被盡量利用,可以把count參數(shù)置為_TRUNCATE,這樣的情況下,實(shí)際上效果相當(dāng)于是將count設(shè)置為sizeOfBuffer - 1。 ? ? 至于C語(yǔ)言環(huán)境下,sprintf_s與_snprintf的對(duì)比: 注意到,_snprintf的參數(shù)用的是count,而sprintf_s的參數(shù)用的是sizeOfBuffer。這很能說(shuō)明問(wèn)題。 看下對(duì)_snprintf的說(shuō)明: 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. ? 也就是說(shuō),_snprintf的count參數(shù)明明白白的就是一個(gè)count。 如果輸出字符串剛好達(dá)到count,由于期待的最大長(zhǎng)度就是count,那么輸出字符串肯定要完整,不能截?cái)唷?/p> 但是假如字符串緩沖區(qū)的大小其實(shí)就是count,這怎么辦?MS VCRT的設(shè)計(jì)者認(rèn)為,在這種情況下應(yīng)該把輸出字符串的長(zhǎng)度告知調(diào)用者,讓調(diào)用者來(lái)決定是否自己添加null-teminate。 換句話說(shuō),調(diào)用_snprintf時(shí)要注意了,必須檢查_snprintf的返回值,如果返回值不是正數(shù),那么還得注意你的字符串緩沖區(qū)并不是null-teminate結(jié)尾的。 ? 總結(jié)來(lái)說(shuō),sprintf_s在緩沖區(qū)不夠大時(shí)會(huì)失敗,失敗時(shí)緩沖區(qū)中是一個(gè)空字符串。 _snprintf不會(huì)失敗,但是必須注意如果緩沖區(qū)不夠大,緩沖區(qū)的內(nèi)容將不是null-teminate的,必須自己注意字符串的結(jié)束。 _snprintf_s結(jié)合了2者的優(yōu)點(diǎn),只要count參數(shù)設(shè)置合理,函數(shù)就不會(huì)因緩沖區(qū)不夠而失敗。 ? 但是觀察_snprintf_s的說(shuō)明,有一個(gè)很有趣的內(nèi)容。 這3族函數(shù)中,有失敗情況的2個(gè)函數(shù)sprintf_s和_snprintf_s中,(再次強(qiáng)調(diào),我這里的失敗的意思是,調(diào)用后緩沖區(qū)里是一個(gè)空字符串),_set_invalid_parameter_handler設(shè)置的錯(cuò)誤處理器,在失敗的情況下會(huì)被調(diào)用。 ? 而截?cái)嗟那闆r下,錯(cuò)誤處理器并不會(huì)被調(diào)用。 ? VC的庫(kù)開發(fā)者總是提供一些怪怪的東西。無(wú)論如何,讓代碼更加安全總是符合大家的總體期望的。 另外補(bǔ)充一下,查閱這些字符串安全函數(shù)的資料的時(shí)候要注意, 對(duì)微軟來(lái)說(shuō),凡是限制字符串復(fù)制長(zhǎng)度的函數(shù),這些設(shè)計(jì)者仍然認(rèn)為是不安全的,因?yàn)檫壿嬌蟻?lái)說(shuō), 這些長(zhǎng)度參數(shù)只是限制了源字符串被復(fù)制的長(zhǎng)度,而不是目標(biāo)緩沖區(qū)的長(zhǎng)度。 也就是說(shuō),微軟的這些設(shè)計(jì)者認(rèn)為,安全的方式其實(shí)是依賴C++的機(jī)制,辨認(rèn)出目標(biāo)緩沖區(qū)的真正大小,以此實(shí)現(xiàn)安全的復(fù)制。 |
轉(zhuǎn)載于:https://www.cnblogs.com/yangxx-1990/p/4877111.html
總結(jié)
以上是生活随笔為你收集整理的sprintf_s与_snprintf与_snprintf_s的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 人民银行支付系统(CNAPS)和中国银联
- 下一篇: int指令01 - 零基础入门学习汇编语