assert用法,原理,改編(C++)

來源:互聯網
上載者:User

轉自: http://hi.baidu.com/hplonline/blog/item/8637ab4470ee268bb3b7dcaa.html

 

最近才發現,原來assert這麼好用啊。。。
再看看是怎麼實現的,又找到了些有趣的東西。

用法:

先包含
#inlcude <assert.h>

在想用的地方給一句:
assert(expression)就可以了。
expression是任意有效邏輯運算式。
比如:

FILE *fp = fopen("in.txt","r") ;
if ( ! fp ){
    exit(0) ;
}
assert(fp != NULL) ;

當expression不滿足時,就會報出一個很醜陋的框框,
然後向控制台輸出assert不滿足的檔案和行號。

具體到debug的時候,
可以撒網式地在各個地方放上認為應該為真的運算式的assert,
說不定哪個就爆了,於是趁機發現了問題。

原理:

只要有源碼就沒有秘密,
所以開啟assert.h,看看裡面是怎麼寫的。

主要的就這兩句:
_CRTIMP void __cdecl _assert(void *, void *, unsigned);
#define assert(exp) (void)( (exp) || (_assert(#exp, __FILE__, __LINE__), 0) )

第一句就乾的就是輸出一些資訊,然後彈出個框框,
順便結束程式這些勾當。
他被調用的時候,是類似於:
_assert("false" , "c:\\1.cpp" , 15)
這樣。

第二句的構造可謂精簡啊,小小一句話還包含了挺多以前沒注意到的事情。

1.短路求值

這個是c的重要特性,在處理&&的時候前面為假則不用繼續,
在處理|| 的時候,前面為真則不用繼續。
形象地說把後面的運算式短路了。

2.單行宏

#exp 產生"exp"這樣的字串
#@a 產生'a'這樣的字元
a##b 把a和b串連起來

第一個用法在這裡見到了,第二個暫時還沒見到用的執行個體。
第三個在a和b是宏的參數的時候有用。否則直接的ab會被當作一個東西。

3.特殊的預定義宏

__FILE__ 會被替換成所在的檔案,字串形式
__LINE__ 會被替換成行號,unsigned類型
__DATE__ 會被替換成日期
__TIME__ 會被替換成時間

其實之前翻過的跟C有關的書應該都講了這些的。
不過拿著一個列表,又不給出真正實用的例子,
當然不知道這些東西是怎麼回事,
久了自然也就忘了。

4.逗號運算式

感覺實在是一個用的很少的事情,
畢竟有多句話的時候,完全可以用分號就行了。
雖然有好多地方在if之類的裡面很壓縮的用逗號運算式寫好幾句話,
其實都可以改得不用逗號運算式的。

其一是逗號運算式的優先順序很低,所以後面那對括弧實在是不可缺少。

其二是逗號運算式的值為最右邊式子的值。
這個估計很多人都記過,但不見得有啥重大意義。
這裡,倒確實是發揮了他的意義。
因為_asert這個函數是void型的,
如果不使用逗號運算式在右邊補個0的話,
會報告:(VC6)
error C2297: '||' : illegal, right operand has type 'void'

改編:

知道是怎麼回事,當然可以很容易做出自己想要的東西。
再說還有asert.h裡面的參照呢。

比如,我嫌預設的_assert彈出的東西看著太壓抑了。。。
就自己寫個就行了。

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

#define MAX_BUFFER 200
void _assert(char *msg , char *file , unsigned line){
    char buf[MAX_BUFFER] ;
    sprintf(buf , "assertion fail:\n%s\nin file:\n%s\non line:\n%d" , msg , file , line) ;
    ::MessageBox(NULL , buf , "assertion failure" , MB_OK) ;
    exit(0) ;
}

#define assert(exp) ((exp) || (_assert(#exp , __FILE__ , __LINE__) , 0) )

int main(){
    assert(1 == 1 && 3 == 4) ;
    return 0 ;
}

效果:

至於我的這個是不是更壓抑。。那不屬於這裡討論的問題了。

反正通過簡單變更_assert函數,可以把相關情況輸出到檔案,
或者選擇另外的方式表達出來,能想到的都可以。

至於assert這個宏,也有可以動手腳的地方。
內建的是assert一個為真的運算式。
有的時候就想assert一個為假的運算式,當他為真的時候發出警告。

比如:

FILE *fp = fopen("in.txt","r") ;
if ( ! fp ){
    exit(0) ;
}
warn(fp == NULL)

套用上面的寫法,既然是為真發警告,那麼用&&去換||就行了。 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.