色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

【C語言進階】sprintf和snprintf的區別

嵌入式物聯網開發 ? 來源:嵌入式物聯網開發 ? 作者:嵌入式物聯網開發 ? 2022-08-31 13:18 ? 次閱讀

C語言上總有些非常相近的接口函數,比如sprintf和snprintf就是其中的一對。以筆者多年的工作經驗,這對接口函數在平時的編程中,使用的頻度是非常高,只是你真的了解它們倆的區別嗎?

帶著這個問題,請跟隨筆者的思路梳理一遍sprintf和snprintf。通過閱讀本文,你將了解到以下內容:

sprintf和snpintf分別是什么?

sprintf和snprintf的區別與聯系

sprintf和snprintf的使用秘訣


sprintf和snpintf分別是什么?


【sprintf】的函數原型如下所示:

/**
功能: 把格式化的數據寫入某個字符串緩沖區
入參:format,輸出字符串的格式化列表,比如"%s %d %c"等
入參: [argument],format對應的不定參數列表,與printf的不定入參類似
出參:buffer,指向一段存儲空間,用于存儲格式化之后的字符串
返回值:返回寫入buffer 的字符數,出錯則返回-1. 如果 buffer 或 format 是空指針,
且不出錯而繼續,函數將返回-1,并且 errno 會被設置為 EINVAL。
備注:它是個變參函數
*/
int sprintf( char *buffer, const char *format, [ argument] … );

【snprintf】的函數原型如下所示:

/**
功能: 有長度限制地,把格式化的數據寫入某個字符串緩沖區
入參:format,輸出字符串的格式化列表,比如"%s %d %c"等
入參: [argument],format對應的不定參數列表,與printf的不定入參類似
入參:size,表示buffer指向存儲空間的大小
出參:buffer,指向一段存儲空間,用于存儲格式化之后的字符串
返回值:返回寫入buffer 的字符數,出錯則返回-1. 如果 buffer 或 format 是空指針,
且不出錯而繼續,函數將返回-1,并且 errno 會被設置為 EINVAL。
備注:它是個變參函數
*/
int snprintf( char *buffer, size_t size, const char *format, [ argument] … );

sprintf和snprintf的區別與聯系


通過對比sprintf和snprintf的函數原型,我們可以發現兩者其實完成相同功能的接口,都是將一段數據經格式化操作之后,轉換成一段字符串,通過接口傳入的buffer指針將格式化的字符串內容輸出。

我們細細比對兩個函數原型,我們會發現snprintf比sprintf多了一個表示buffer指針指向存儲空間的大小的入參size,那么它到底有什么作用呢?我們先來分析下snprintf接口的內部行為與size的關系:

如果格式化后的字符串長度 < size,則將此字符串全部復制到str中,并給其后添加一個字符串結束符('\0')

如果格式化后的字符串長度 >= size,則只將其中的(size-1)個字符復制到str中,并給其后添加一個字符串結束符('\0'),返回值為欲寫入的字符串長度。

看完這一段解釋之后,大概你就明白了,原來snprintf就是sprintf的安全版本,因為單從sprintf的內部行為來看,它是沒有辦法保證對buffer指針的賦值操作是沒有越界的,因為它壓根就不知道buffer的存儲空間多少有多大,所以它只能認為是【無窮大】。但是snprintf通過入參size,恰好可以很好的解決這個問題,它可以很明確的告知snprintf的內部操作,以size作為界線,當輸出的字符串長度要超過size時,應做出裁剪輸出。在很多的編程寶典中,都是推薦使用snprintf,而要求編程者盡可能地避免使用sprintf這種不安全接口。


sprintf和snprintf的使用秘訣


我們通過一段測試代碼來展示下兩者的使用方法,以及上一小結中提及的可能導致buffer溢出的嚴重問題:

//sprintf的用法
{
    char buffer[10]; //定義一個只有10個字節空間的buffer數組
    const int a = 12345; //定義一個int型的常量
    const char *msg = "012345678901234567890"; //定義一個長度為20字節的字符串常量

    sprintf(buffer, "%d", a); //將a變量按int類型打印成字符串,輸出到buffer中
    /*
    輸出分析:
    輸出結果: buffer="12345"
    因為最后輸出的buffer內容長度不超過10字節,所以此時sprintf操作是沒有溢出風險的
    */

    sprintf(buffer, "%d+%s", a, msg); //將a變量和msg字符串通過“+”連接成一個字符串
    /*
    輸出分析:
    由于buffer只有10個字節空間,而sprintf在執行字符串格式化輸出的時,并不知道buffer的真實長度,
    所以它會將"12345+012345678901234567890"這整個字符串都拷貝到buffer空間上,這就導致了buffer存儲空間溢出了。
    從存儲位置上分析,我們知道buffer空間屬于一個棧空間,在它自己的10字節之外的空間很明顯是其他棧變量的存儲空間,
    一旦sprintf將10字節外的其他空間也操作了,這就有可能破壞了其他棧變量的內容,這有可能是致命的。
    */
}

//snprintf的用法
{
    char buffer[10]; //定義一個只有10個字節空間的buffer數組
    const int a = 12345; //定義一個int型的常量
    const char *msg = "012345678901234567890"; //定義一個長度為20字節的字符串常量

    snprintf(buffer, sizeof(buffer), "%d", a); //將a變量按int類型打印成字符串,輸出到buffer中
    /*
    輸出分析:
    輸出結果: buffer="12345"
    因為最后輸出的buffer內容長度不超過10字節,所以snprintf操作是沒有溢出風險的;
    此種情況下,使用sprintf和snpintf都可以得到同樣的結果,且都不會產生數組溢出。
    */

    sprintf(buffer, sizeof(buffer), "%d+%s", a, msg); //將a變量和msg字符串通過“+”連接成一個字符串
    /*
    輸出分析:
    輸出結果是: buffer="12345+0123",加上一個'\0'的字符串結束符,
    剛好占用了buffer的10字節的存儲空間,不存在任何的buffer溢出風險。而"0123"后面的字符串都被snprintf內部裁剪掉了,這就體現了snprintf操作安全的特性。
    */
}

通過以上分析,我們很好地認識到了sprintf的操作是不安全的。在C語言的語法上,指針的靈活性也帶來可能導致的指針溢出風險,而snprintf恰好就是解決了這個困惑的sprintf升級版本。

類似的,還有strcat和strncat、strcpy和strncpy等等。通過本文的方法,讀者也可以寫一小段測試代碼,好好捋一捋本文提及的這幾組函數,一起領悟下其他的奧秘和使用風險吧。

以上總結,均來自筆者多年的實踐經驗,如有發現不正確的陳述或錯誤的觀點,還望讀者指正,感激不盡。

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C語言
    +關注

    關注

    180

    文章

    7604

    瀏覽量

    136692
  • 函數
    +關注

    關注

    3

    文章

    4327

    瀏覽量

    62573
  • sprintf
    +關注

    關注

    0

    文章

    6

    瀏覽量

    4020
收藏 人收藏

    評論

    相關推薦

    嵌入式C語言進階之道

    嵌入式C語言進階之道
    發表于 08-20 16:02

    c語言之高手進階

    c語言之高手進階 從點滴開始 楊帆起航
    發表于 07-04 16:14

    C語言進階

    C語言進階見附件
    發表于 08-13 15:51

    C語言進階書分享!

    挺好的。c語言進階.pdf (1.78 MB )
    發表于 10-16 02:44

    sprintf與printf函數的區別

    單片機中Sprint函數:說明1:使用該函數時必須包含stdio.h頭文件,否則容易卡死程序說明2:sprintf與printf函數的區別:二者功能相似,但是sprintf函數打印到字符串中(將數值
    發表于 08-23 06:18

    單片機IO擴展(進階)程序集合【C語言

    單片機IO擴展(進階)程序集合【C語言】。
    發表于 01-06 11:04 ?23次下載

    sprintf和printf的區別

    的變量,最終函數就會用相應位置的變量來替代那個說明符,產生一個調用者想要的字符串。那么接下來我們一起了解一下sprintf與printf的區別
    發表于 11-28 14:41 ?1.7w次閱讀

    C51單片機C語言與標準C語言有什么區別

    一:C51(單片機C語言)與標準C語言區別1、 C
    發表于 10-09 08:00 ?134次下載
    <b class='flag-5'>C</b>51單片機<b class='flag-5'>C</b><b class='flag-5'>語言</b>與標準<b class='flag-5'>C</b><b class='flag-5'>語言</b>有什么<b class='flag-5'>區別</b>?

    C語言進階學習課件資料合集

    本文檔的主要內容詳細介紹的是C語言進階學習課件資料合集包括了:第1節-數據的存儲,第2節-指針的進階,第3節-字符串+內存函數的介紹,第4節-自定義類型詳解(結構體+枚舉+聯合),第
    發表于 07-14 08:00 ?11次下載
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>的<b class='flag-5'>進階</b>學習課件資料合集

    C語言進階】“數組指針”和“指針數組”都是啥跟啥?

    C語言進階】“數組指針”和“指針數組”都是啥跟啥?
    的頭像 發表于 08-31 13:21 ?1912次閱讀

    C語言進階C語言指針的高階用法

    C語言進階C語言指針的高階用法
    的頭像 發表于 08-31 13:24 ?2318次閱讀

    C語言進階】利用assert高效排查你的C程序

    C語言進階】利用assert高效排查你的C程序
    的頭像 發表于 08-31 13:27 ?2109次閱讀

    C語言進階之嵌入式系統高級C語言編程

    電子發燒友網站提供《C語言進階之嵌入式系統高級C語言編程.rar》資料免費下載
    發表于 11-18 10:32 ?1次下載
    <b class='flag-5'>C</b><b class='flag-5'>語言</b><b class='flag-5'>進階</b>之嵌入式系統高級<b class='flag-5'>C</b><b class='flag-5'>語言</b>編程

    vb語言c++語言區別

    VB語言C++語言是兩種不同的編程語言,雖然它們都屬于高級編程語言,但在設計和用途上有很多區別
    的頭像 發表于 02-01 10:20 ?2258次閱讀

    PLC編程語言C語言區別

    在工業自動化和計算機編程領域中,PLC(可編程邏輯控制器)編程語言C語言各自扮演著重要的角色。盡管兩者都是編程語言,但它們在多個方面存在顯著的區別
    的頭像 發表于 06-14 17:11 ?2784次閱讀
    主站蜘蛛池模板: 国产精品VIDEOS麻豆TUBE| AV一区AV久久AV无码| 坠落的丝袜美人妻| 最近中文字幕2019免费版日本| 97国产在线观看| 大香伊人中文字幕精品| 国产色精品久久人妻无码看片软件| 好想被狂躁A片免费久99| 久久草这里全是精品香蕉频线观| 麻豆乱码一卡二卡三卡视频| 胖老太与人牲交BBWBBW高潮| 无人区乱码1区2区3区网站| 亚洲一区自拍高清亚洲精品| 131美女爱做视频午夜剧场| 扒开美女嫩bbb| 国产性夜夜春夜夜爽1A片| 久久视频这有精品63在线国产| 欧美日韩国产码在线| 无码内射成人免费喷射| 依人青青青在线观看| 成年人视频在线免费播放| 国产在线高清视频| 免费人成在线观看网站视频| 十八禁肉动漫无修在线播放| 一区三区在线专区在线| 超碰在线97av视频免费| 狠狠色狠狠色综合日日2019| 牛牛自拍国产免费视频| 羞羞答答dc视频| 999精品免费视频| 脱女学小内内摸出水网站免费| 亚洲成在人线视频| 99pao成人国产永久免费视频 | 亚洲精品久久久无码一区二区| 最新日本免费一区| 国产成人精品免费视频软件| 精品人妻一区二区三区视频53| 青青草偷拍国产亚洲欧洲| 亚洲理论片在线中文字幕| RUNAWAY韩国动漫免费网| 精品国产乱码久久久久久免费|