在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【C語言進(jìn)階】利用assert高效排查你的C程序

嵌入式物聯(lián)網(wǎng)開發(fā) ? 來源:嵌入式物聯(lián)網(wǎng)開發(fā) ? 作者:嵌入式物聯(lián)網(wǎng)開發(fā) ? 2022-08-31 13:27 ? 次閱讀
眾所周知,我們在實際開發(fā)C程序的時候,往往是編碼容易——調(diào)試?yán)щy,修改容易——排查困難。我們在開發(fā)過程中,debug占據(jù)了我們很大一部分的時間,而正確地使用各種編碼手段,可以有效地提升排查問題代碼的效率。筆者從自己的實踐經(jīng)驗出發(fā),給大家分享一個用于編碼/調(diào)試階段高效發(fā)現(xiàn)問題代碼的利器,這就是大名鼎鼎的**assert**。通過閱讀本文,你將了解到以下內(nèi)容:
  • 什么是assert?
  • assert有什么用?
  • assert怎么使用?
  • assert的常規(guī)操作有哪些?

什么是assert?


? assert它的中文含義是“斷言”,它被包含在中,往往給使用者呈現(xiàn)的形式為: assert() 。因此,很多開發(fā)者認(rèn)為它就是一個函數(shù),可能它的原型就是void assert(int expression); 但研究過assert.h的,一定會發(fā)現(xiàn),其實并不是。

? assert的真身,其實是一個宏定義,只不過是一個帶參數(shù)輸入的宏定義,與我們之前一篇八卦Linux內(nèi)核設(shè)計的max宏定義 (【Linux內(nèi)核】從小小的宏定義窺探Linux內(nèi)核的精妙設(shè)計)類似的。廬山真面目如下所示:

#define assert(e) ((e) ? (void)0 : _assert(#e, __FILE__, __LINE__))

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zc6EAp8U-1661923571346)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

? 從它的定義,我們可以很清晰的知道,真正起到打印作用的是_assert,而它才是真正的一個函數(shù)。原型為:

void _assert(const char *e, const char *file, int line);

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-dax1ldZf-1661923571352)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]


assert有什么用?


? 本文的主題是利用assert高效排查問題代碼,自然assert的用途就是排查代碼;但是,具體它的功能是怎么體現(xiàn)呢?假設(shè)有如下代碼,一個測試函數(shù)的實現(xiàn)片段:

int test_function(int a, int *b)
{
    assert(a > 1);  /* 斷言:入?yún)的值一定大于1 */
    assert(b);      /* 斷言: 入?yún)指針一定不是NULL */

    /* Do other things here ... */
}

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ejym7Jij-1661923571353)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

? 如代碼所示,有一個測試函數(shù)test_function,接收2個入?yún)ⅲ粋€是int型的a變量,一個int *類型的b指針;在函數(shù)的開始,我們就用assert分別對a和b做了斷言,確保它們有正確的輸入。假設(shè)我們有如下的函數(shù)調(diào)用的測試代碼:

{
    int a = 7;
    int *b = &a;
    
    test_function(a, b);

    /* Do other things here ... */
}

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-E4QQ143R-1661923571355)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

? 很明顯,當(dāng)如上代碼調(diào)用test_fucntion時,內(nèi)部的兩個assert判斷均為【真】,那么什么事情也不會發(fā)生,assert就像一個優(yōu)雅的淑女,靜靜地站在那里看著你。

? 當(dāng)我們的測試代碼做如下調(diào)整:

{
    int a = 0;
    int *b = &a;
    
    test_function(a, b);

    /* Do other things here ... */
}

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qPbDKDBb-1661923571357)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

? 很明顯,test_function的第一個assert語句不為【真】,那么它就像山洪一樣要爆發(fā)了,終止程序運行的同時,會輸出類似的錯誤提示: Assertion failed: a > 1,file xxx.c, line 128,這段錯誤提示,不僅告訴了我們哪個條件判斷出錯了,并且還告訴了我們出錯的位置在哪個文件的哪一行,這是多么智能啊!由此可見,它真正的威力在于【代碼出錯】時,即當(dāng)代碼沒有按照我們的斷言進(jìn)行時,我們就應(yīng)該停下來,排查下為何會有錯誤的參數(shù)輸入,這樣我們就可以將bug在出現(xiàn)苗頭的時候就把它消滅掉。


assert怎么使用?


? 其實,上面的示例代碼已經(jīng)展示了如何使用assert,但是我們需要補充的是,一般在使用assert斷言語句的時候,需要在對應(yīng)的.c文件加上對assert.h的引用,否則編譯會報錯誤。

? assert這么智能的利器是非常有利于我們寫出高質(zhì)量不易出錯的代碼的,通常富有經(jīng)驗的程序員都會很擅長使用assert語句,把assert打在恰當(dāng)?shù)恼Z句中,可以最大限度地提升我們的代碼質(zhì)量。但是,很多開發(fā)者開始有疑惑了,要是每條語句,每個判斷都加上assert,那么就算全部assert的情況都是【真】,也夠CPU忙一會了,這樣似乎有些浪費CPU的計算能力,以追求高效的C語言編程,可容不下這樣的事情發(fā)生。那,這可怎么辦呢?

? 為避免以上情況的發(fā)生,我們作為assert的使用者,一般只需要在開發(fā)調(diào)試階段才使用assert,而在正式發(fā)布的版本是需要去掉assert的。這樣疑惑就更大了,發(fā)布版本一條條刪掉assert調(diào)用,萬一刪錯了代碼呢?設(shè)計者總是聰明的,他們也早就想到了這一點,這不他們也提供了解決方案。開頭的時候,我們介紹了assert是一個宏,但并沒有完全展示它的全貌?,F(xiàn)在開始展示它的真容:

#ifdef NDEBUG
#define assert(e) (void)0
#else
#define assert(e) ((e) ? (void)0 : _assert(#e, __FILE__, __LINE__))
#endif

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-69cPczpO-1661923571359)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]

? 聰明的你,一定也發(fā)現(xiàn)了,我們只需要在.c文件#include 之前,加上一句#define NDEBUG 1就可以把相應(yīng).c中的assert(e)全部變成((void)0);而((void)0)本身是個無效調(diào)用代碼,在實際的編譯過程中是會被優(yōu)化掉的,這樣我們僅增加對NDEBUG(NO DEBUG的意思)的宏定義,就可以把全部的assert給摒棄了,是不是很智能呢?


assert的常規(guī)操作有哪些?


? 正如上面所述,assert這么智能,但是我們也不能濫用,只需要在恰當(dāng)?shù)奈恢米鳛樘囟ǖ呐袛啵煌ǔ碚f,我們有以下一些情景可以考慮使用assert語句:

  • 函數(shù)的入?yún)⑴袛?,對錯誤的入?yún)⒓皶r處理
  • 對重點調(diào)用的系統(tǒng)函數(shù)的返回結(jié)果做判斷,使用assert保證系統(tǒng)調(diào)用的結(jié)果是正確的,避免外部使用不正確的系統(tǒng)調(diào)用而出現(xiàn)錯上加錯的情況;
  • switch語句中,如果不允許出現(xiàn)default的情況,可以考慮在default分支中加入assert(0);
  • 執(zhí)行計算時,做計算的輸入或計算結(jié)果的輸出等做下判斷,比如除數(shù)不能為0,比如一個百分比值不能超過100%等等。

? 綜述,assert是把雙刃劍,出錯時它能很優(yōu)秀地暴露問題代碼,非常有利于我們排查代碼,從而以最快的速度找到問題并解決問題;同時,它的頻繁調(diào)用,一定程度上加上了CPU的處理,做一些無畏的判斷,“簡直就是在浪費生命”。所以,在實際開發(fā)過程中,我們務(wù)必要嚴(yán)謹(jǐn)細(xì)致地使用assert,讓它更好地為我們服務(wù)。

? 只有不自負(fù)且思維嚴(yán)謹(jǐn)?shù)娜瞬拍苁褂煤胊ssert,我們只有做到了不自負(fù),不對自己的代碼打100%的包票,相信是代碼總會有出錯的時候,才會逐步養(yǎng)成思維嚴(yán)謹(jǐn)?shù)牧?xí)慣,反而對自己的代碼質(zhì)量有更大的提升。

? 本文對assert的介紹和使用做了一番總結(jié),文中難免有紕漏之處,還望讀者誠心指正,感謝。

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

    關(guān)注

    180

    文章

    7605

    瀏覽量

    136959
  • C程序
    +關(guān)注

    關(guān)注

    4

    文章

    254

    瀏覽量

    36041
  • ASSERT
    +關(guān)注

    關(guān)注

    0

    文章

    17

    瀏覽量

    7252
收藏 人收藏

    評論

    相關(guān)推薦

    C語言assert的使用

    assert意思是斷言,常用在程序的DEBUG版本中。
    發(fā)表于 07-21 14:51 ?860次閱讀

    C語言assert(斷言)簡介

    assert的功能,條件為真,程序繼續(xù)執(zhí)行;如果斷言為假(false),則程序終止。
    的頭像 發(fā)表于 11-17 16:33 ?1168次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b><b class='flag-5'>assert</b>(斷言)簡介

    C語言進(jìn)階

    C語言進(jìn)階見附件
    發(fā)表于 08-13 15:51

    C語言進(jìn)階書分享!

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

    100個經(jīng)典C語言程序

    c語言編寫,c語言的100個經(jīng)典程序,單片機的應(yīng)用,開發(fā)利用
    發(fā)表于 12-17 11:46 ?11次下載

    時鐘設(shè)計程序C語言

    時鐘設(shè)計程序。時鐘設(shè)計程序。時鐘設(shè)計程序C語言】時鐘設(shè)計程序
    發(fā)表于 12-28 12:02 ?0次下載

    單片機IO擴展(進(jìn)階)程序集合【C語言+匯編】

    單片機IO擴展(進(jìn)階)程序集合【C語言+匯編】
    發(fā)表于 01-06 11:03 ?8次下載

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

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

    DSP C2000程序員高手進(jìn)階

    DSP C2000程序員高手進(jìn)階 PDF 版
    發(fā)表于 05-06 15:13 ?33次下載

    DSP C2000程序員的高手進(jìn)階

    DSP C2000程序員的高手進(jìn)階
    發(fā)表于 10-16 13:16 ?20次下載
    DSP <b class='flag-5'>C</b>2000<b class='flag-5'>程序</b>員的高手<b class='flag-5'>進(jìn)階</b>

    C語言進(jìn)階學(xué)習(xí)課件資料合集

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

    C語言進(jìn)階】sprintf和snprintf的區(qū)別

    C語言進(jìn)階】sprintf 和 snprintf 真的沒有區(qū)別嗎?
    的頭像 發(fā)表于 08-31 13:18 ?1.2w次閱讀

    C語言進(jìn)階C語言指針的高階用法

    C語言進(jìn)階C語言指針的高階用法
    的頭像 發(fā)表于 08-31 13:24 ?2343次閱讀

    C語言進(jìn)階之嵌入式系統(tǒng)高級C語言編程

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

    C語言構(gòu)建高效的嵌入式程序

    嵌入式工程師在編寫C語言程序時,需要注重效率和清晰的思路。本文將通過解析經(jīng)典問題“猴子選大王”來展示如何用C語言思維方式構(gòu)建
    的頭像 發(fā)表于 12-21 09:27 ?638次閱讀
    主站蜘蛛池模板: 国产美女精品一区二区三区| 哪个网站可以看av| 国产日韩一区二区三区| 五月婷亚洲| 特黄日韩免费一区二区三区| 激情五月婷婷基地| 日本黄色影片| 亚欧洲乱码专区视频| 国产欧美日韩视频免费61794| 夜夜夜操| 福利片欧美| 毛片高清一区二区三区| 日韩系列| 四虎永久在线精品2022| 永久在线观看www免费视频| 人人添人人澡人人澡人人人爽| 西西人体大胆高清啪啪欧洲| 久久亚洲国产午夜精品理论片| 午夜精品久久久久久91| 77米奇| 成人在色线视频在线观看免费大全| 免费看大尺度视频在线观看| 四虎精品久久久久影院| 午夜性影院| 日本黄色短片| 国产亚洲精品自在久久77| 免费观看四虎精品成人| 国产美女在线免费观看| 亚洲精品视频在线| 午夜在线观看网站| a亚洲天堂| 97黄网| 免费在线黄网| 久久www免费人成看片色多多| 天天插日日插| 天堂8在线天堂bt| jlzzjlzzjlzz日本亚洲| 午夜色大片在线观看| 男女视频在线| 天堂avwww| 日本三级网站在线观看|