C語言C++中assert的用法

2021-03-02 C語言與CPP編程

斷言assert原型

void assert(int expression);

assert宏的原型定義在<assert.h>中,其作用是先計算表達式expression的值為假(即為0),那麼它就先向stderr列印一條出錯信息,然後通過條用abort來終止程序;

使用assert的缺點是,頻繁的調用會極大的影響程序的性能,增加額外的開銷。

在調試結束後,可以通過在包含#include 的語句之前插入 #define NDEBUG 來禁用assert調用,示例代碼如下:

1 #include
2 #define NDEBUG
3 #include

斷言assert使用規則
#include <stdio.h>
#include <assert.h>
int main(void)
{
int i;
i = 1;
assert(i++);
printf(「%d\n」,i);
return 0;
}

看運行結果,如果給定的i初始值為1,所以其運行結果不會為錯,如下圖所示

很顯然是2,不會出錯

如果將i初始值改成0,那麼就會出現如下錯誤:

出現異常

上面這個錯誤是很典型異常,可以考慮用assert排查。

根據提示我們很快就能定位到錯誤點,就在assert(i++)處;既然assert這麼便於定位出錯點,在工程中使用它就顯得很有必要;但其也有一定的使用規則;

斷言語句不會永遠被執行,可以屏蔽也可以啟用,這就要求assert不管是在屏蔽還是啟用狀態下都不能對我們本身代碼有所影響,這樣剛才我們在代碼中使用的assert(i++)就不行,因為如果禁用了assert,那i++就不能執行;正確的做法應該是:assert(i);i++;那麼我們一般在什麼情況下使用斷言呢?

主要體現在以下幾個方面:

1. 可以在預計正常情況下程序不會到達的地方放置斷言。(如assert(0);)3. 使用斷言檢測類的不變狀態,確保任何情況下,某個變量的狀態或範圍必須滿足。斷言assert使用規則

當然我們在使用斷言的過程中會有一些我們應該注意的事項和養成一些良好的習慣,如:

1. 每個assert只檢驗一個條件,因為同時檢驗多個條件時,如果斷言失敗,我們就無法直觀的判斷哪個條件失敗;

無法直觀的判斷哪個條件失敗:

assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);

只檢驗一個條件,比較直觀:

assert(nOffset >= 0);
assert(nOffset+nSize <= m_nInfomationSize);

2. 不能使用改變環境的語句,就像我們上面的代碼改變了i變量,在實際編寫代碼的過程中是不能這樣做的;

例如:

assert(i++ < 100)

不好:這是因為如果出錯,比如在執行之前i=100,那麼這條語句就不會執行,那麼i++這條命令就沒有執行。

assert(i < 100)
i++;

正確。

3. assert和後面的語句應該空一行,以形成邏輯和視覺上的一致性,也算是一種良好的編程習慣,讓編寫的代碼有一種視覺上的美感;

程序一般分為Debug 版本和Release 版本,Debug 版本用於內部調試,Release 版本發行給用戶使用。斷言assert 是僅在Debug 版本起作用的宏,它用於檢查"不應該"發生的情況。

int resetBufferSize(int nNewSize)
{
//功能:改變緩衝區大小,
//參數:nNewSize 緩衝區新長度
//返回值:緩衝區當前長度
//說明:保持原信息內容不變 nNewSize<=0表示清除緩衝區
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);
...
}

在我們使用C語言/C++做工程項目時,如果我們能在代碼中合理的使用assert,能使我們創建更穩定、質量更好且不易於出錯的代碼;當需要在一個值為FALSE時中斷當前操作的話就可以使用斷言。

單元測試必須使用斷言;另外除了類型檢查和單元測試外,斷言還提供了一種確定各種特性是否在程序中得到維護的極好的方法;

最近原創推薦

字符串操作的全面總結

代碼防禦性編程的十條技巧

 九種查找算法

 十大經典排序算法(動態演示+代碼)

 C語言與C++面試知識總結

  數據結構之堆棧

 一文輕鬆理解內存對齊

點【在看】是最大的支持 

讚賞誠可貴,在看轉發價更高

相關焦點

  • C/C++ assert()函數用法總結與注意事項
    簡介assert宏的原型定義在<assert.h>中,其作用是如果它的條件返回錯誤,則終止程序執行。/a.out  a.out: badptr.c:14: main: Assertion `fp' failed.已放棄使用assert()的原因是,頻繁的調用會極大的影響程序的性能,增加額外的開銷。
  • C/C assert()函數用法總結與注意事項
    簡介assert宏的原型定義在中,其作用是如果它的條件返回錯誤,則終止程序執行。原型定義:#include void assert( int expression );assert的作用是先計算表達式 expression ,如果其值為假(即為0),那麼它先向stderr列印一條出錯信息,然後通過調用 abort 來終止程序運行。
  • assert函數-論java中assert函數和Python、PHP、C語言assert函數
    assert函數廣泛在java、Python、PHP、C語言中存在,都有統一的意義,用業界語言稱之為"斷言"。最初的出發點都是為了方便調試而設計的,但是最近越來越多的開發者不分測試環境和正式環境濫用assert函數,引發了我對廣大程式設計師朋友的擔憂,故寫此篇文章普及assert函數常識,避免各位朋友濫用assert函數。簡單的概況在各個語言中assert函數的意義:如果表達式的值為假,整個程序將退出,並輸出一條錯誤信息。如果表達式的值為真則繼續執行後面的語句。
  • C語言程序開發中常用的assert,到底有什麼用,有哪些好處?
    C語言中的 assert() 方法可以診斷程序 bug,使用之前應該包含 <assert.h> 頭文件,它的C語言原型如下,請看:void assert(int expression);參數 expression 可以是任意
  • C++語言中std::array的神奇用法總結
    在這篇文章裡,我會從各個角度介紹下std::array的用法,希望能帶來一些啟發。本文的代碼都在C++17環境下編譯運行。當前主流的g++版本已經能支持C++17標準,但是很多版本(如gcc 7.3)的C++17特性不是默認打開的,需要手工添加編譯選項-std=c++17。
  • C 語言會比 C++ 快?
    gcc / clang 中的調試運行性能有點退步,我相信這是因為我的替換代碼中使用 assert 來對每個 operator[] 訪問執行邊界檢查,而在 libc ++ 和 libstdc ++ 中,它們分別使用 _GLIBCXX_ASSERTIONS 和_LIBCPP_DEBUG 單獨定義來完成邊界檢查控制的。
  • 面試:C/C++常見庫函數實現
    www.cnblogs.com/wxquare/p/5014445.html1、void *mymemcpy(void *dest, const void* src, size_t n);內存拷貝函數,memcpy函數的功能是從源src所指的內存地址的起始位置開始拷貝n個字節到目標dest所指的內存地址的起始位置中
  • C語言strcmp和strcpy的用法
    一、c語言strcmp()用法原型:int strcmp(const char *s1, const char *s2);頭文件:#include
  • 斷言(assert)的用法
    本文轉載自【微信公眾號:雲深之無跡,ID:TT1827652464】經微信公眾號授權轉載,如需轉載與原文作者聯繫斷言(assert)的用法我一直以為 assert 僅僅是個報錯函數,事實上,它居然是個宏,並且作用並非"報錯"。
  • C語言陷阱與技巧20節,自定義「編譯時」assert方法,在代碼編譯階段...
    在C語言程序開發中,程式設計師寫代碼時應該考慮的「面面俱到」,這樣才能寫出功能穩定的程序。例如,在實現 open() 函數時,先完成它的功能固然是重要的,但是程式設計師還需要考慮各種「意外」,比如下面這種情況。
  • C語言,C++,C ,Java之間的關係
    C語言,C++,C#,Java,這幾種語言,應該說是當前最流行,也是最基礎的計算機語言。是不是有些人看著會頭大,大腦會不叫混亂,一個計算機怎麼會有那麼的的語言呢?看著就頭大。現在,小編先來給大家說下計算機語言的發張,一臺計算機最本質的語言是機器語言,由01010101的代碼組成,CPU處理的也是由由010101的代碼組成的數據。但是,這種語言太簡單了,不好理解。就來個數字組成的語言,可以用來表達一句話,一個數字,圖像,字母......也許只有計算機可以理解,反正小編是不知道什麼意思。
  • C語言與C++混合開發?命中會遇見的extern "C"!
    gcc -o add.o -c add.cgcc -o hello.o -c hello.cppgcc add.o hello.o -o hello連結出錯,我們看下出錯信息:這裡就是這一節要講的,cpp編譯生成的目標文件中的符號定義,跟c生成出來的有區別,符號命名的方式不一樣。這裡是add.o裡面add符號,可以發現不一樣。
  • STM32中C語言知識點:初學者必看,老鳥複習(長文總結)
    其實C語言是可以邊學單片機邊學的,學單片機的一些例程中,遇到不懂的C語言知識,再去查相關的知識點,這樣印象才會深刻些。下面就列出了一些STM32中重要的C語言知識點,初學的小夥伴可以多讀幾遍,其中大多知識點之前都有寫過,這裡重新整理一下,更詳細地分析解釋可以閱讀附帶的連結。as
  • c語言中的字符串操作函數
    一,常量指針與指針常量先來補充一個上篇文章 手把手教你深入理解c/c++中的指針 我在講述指針中的一個問題,有人說常量指針與指針常量這兩個概念總是混淆怎麼辦,例如:int a = 100;const int * p = &a;  int const * p = &a;
  • C語言中的字符串操作函數
    我們知道,c/c++之所以使用起來靈活,很大原因歸因於它能夠它對能夠對內存的直接操作,所以本文我主要講述一下c中的字符串操作函數。一,常量指針與指針常量先來補充一個上篇文章 手把手教你深入理解c/c++中的指針 我在講述指針中的一個問題,有人說常量指針與指針常量這兩個概念總是混淆怎麼辦,例如:int a = 100;const int * p = &a;  int const * p = &a;
  • python+C、C++混合編程的應用
    排序說明不了語言的好壞,反應的不過是某個軟體開發領域的熱門程度。語言的發展不是越來越common,而是越來越專注領域。有的語言專注於簡單高效,比如python,內建的list,dict結構比c/c++易用太多,但同樣為了安全、易用,語言也犧牲了部分性能。
  • 一文帶你了解c++和c中字符串的使用
    ,但是如果你對c語言理解不是很深的話,那你可能就不能"享受"到這裡面的"美味"用法了,既然標題都標註了這個,我也不賣關子,下面會有總結分享的。說完了c,那麼對於我們的c++來說,它定義字符串就簡單多了,因為有關鍵字來定義,你一看就知道。那麼下面大家就隨著我的筆步一起來看看究竟吧!
  • 九大程式語言優缺點第四期:c++
    上一期給大家介紹了C語言,理所應當的本期給大家了解下C語言的超集,c++那麼接下來給大家介紹主流程式語言:C++、JavaScript、C#、Ruby、PHP以及Objective-C,對於這幾種語言,大家都能看到由其打造的頂尖應用,我們一起來了解一下吧。
  • Python assert斷言函數及用法
    Python assert 語句,又稱斷言語句,可以看做是功能縮小版的 if 語句,它用於判斷某個表達式的值,如果值為真,則程序可以繼續往下執行
  • C語言與C++面試知識總結
    volatile 關鍵字聲明的變量,每次訪問時都必須從內存中取出值(沒有被 volatile 修飾的變量,可能由於編譯器的優化,從 CPU 寄存器中取值)const 可以是 volatile (如只讀的狀態寄存器)assert() 斷言,是宏,而非函數。