NO IMAGE

NVIDIA面試筆試題之一:

assert.h是c標準庫的一個標頭檔案,該標頭檔案的主要目的就是提供一個assert的巨集定義。

assert只是對所給的表示式求值,就像if判斷語句中一樣,然後如果該值為真則正常執行,否則報錯,並呼叫abort(),產生異常中斷,exit出來。

該巨集可以遮蔽掉,只需在包含assert.h之前#define NDEBUG,想開再#undef。從這裡可以看出預處理帶來的方便。

函式名: assert

  功 能: 測試一個條件並可能使程式終止

  用 法: void assert(int test);

  程式例:

  #include <assert.h>

  #include <stdio.h>

  #include <stdlib.h>

  struct ITEM {

  int key;

  int value;

  };

  

  void additem(struct ITEM *itemptr) {

  assert(itemptr != NULL);

  

  }

  int main(void)

  {

  additem(NULL);

  return 0;

  }

  assert() 函式用法

  assert巨集的原型定義在<assert.h>中,其作用是如果它的條件返回錯誤,則終止程式執行,原型定義:

  #include <assert.h>

  void assert( int expression );

  assert的作用是現計算表示式 expression ,如果其值為假(即為0),那麼它先向stderr列印一條出錯資訊,

  然後通過呼叫 abort 來終止程式執行。

  請看下面的程式清單badptr.c:

  #include <stdio.h>

  #include <assert.h>

  #include <stdlib.h>

  int main( void )

  {

  FILE *fp;

  fp = fopen( “test.txt”, “w” );//以可寫的方式開啟一個檔案,如果不存在就建立一個同名檔案

  assert( fp ); //所以這裡不會出錯

  fclose( fp );

  fp = fopen( “noexitfile.txt”, “r” );//以只讀的方式開啟一個檔案,如果不存在就開啟檔案失敗

  assert( fp ); //所以這裡出錯

  fclose( fp ); //程式永遠都執行不到這裡來

  return 0;

  }

  [[email protected] error_process]# gcc badptr.c

  [[email protected] error_process]# ./a.out

  a.out: badptr.c:14: main: Assertion `fp’ failed.

  已放棄

  使用assert的缺點是,頻繁的呼叫會極大的影響程式的效能,增加額外的開銷。

  在除錯結束後,可以通過在包含#include <assert.h>的語句之前插入 #define NDEBUG 來禁用assert呼叫,示例程式碼如下:

  #include <stdio.h>

  #define NDEBUG

  #include <assert.h>

  用法總結與注意事項:

  1)在函式開始處檢驗傳入引數的合法性

  如:

  int resetBufferSize(int nNewSize)

  {

  //功能:改變緩衝區大小,

  //引數:nNewSize 緩衝區新長度

  //返回值:緩衝區當前長度

  //說明:保持原資訊內容不變 nNewSize<=0表示清除緩衝區

  assert(nNewSize >= 0);

  assert(nNewSize <= MAX_BUFFER_SIZE);

  …

  }

  2)每個assert只檢驗一個條件,因為同時檢驗多個條件時,如果斷言失敗,無法直觀的判斷是哪個條件失敗

  不好: assert(nOffset>=0 && nOffset nSize<=m_nInfomationSize);

  好: assert(nOffset >= 0);

  assert(nOffset nSize <= m_nInfomationSize);

  3)不能使用改變環境的語句,因為assert只在DEBUG個生效,如果這麼做,會使用程式在真正執行時遇到問題

  錯誤: assert(i < 100)

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

  正確: assert(i < 100)

  i ;

  4)assert和後面的語句應空一行,以形成邏輯和視覺上的一致感

  5)有的地方,assert不能代替條件過濾

  注意:當對於浮點數:

  #include<assert.h>

  // float pi=3.14;

  // assert(pi=3.14); //

  float pi=3.14f;

  assert (pi=3.14f);

  ———————————————————

  在switch語句中總是要有default子句來顯示資訊(Assert)。

  int number = SomeMethod();

  switch(number)

  {

  case 1:

  Trace.WriteLine(“Case 1:”);

  break;

  case 2:

  Trace.WriteLine(“Case 2:”);

  break;

  default :

  Debug.Assert(false);

  break;

  }