通过一个例子来说明

#include <stdio.h>
#include <assert.h>

int main(int argc, char* argv[])
{
  int i = 1;
  assert(i>0);

  printf("i=%d\n", i);

  return 0;
}
$ gcc -E assert.c -o assert.E
$ gcc -DNDEBUG -E assert.c -o assert_NODEBUG.E


assert.E

...
# 4 "assert.c"
int main(int argc, char* argv[])
{
  int i = 1;
  
# 7 "assert.c" 3 4
 ((void) sizeof ((
# 7 "assert.c"
 i>0
# 7 "assert.c" 3 4
 ) ? 1 : 0), __extension__ ({ if (
# 7 "assert.c"
 i>0
# 7 "assert.c" 3 4
 ) ; else __assert_fail (
# 7 "assert.c"
 "i>0"
# 7 "assert.c" 3 4
 , "assert.c", 7, __extension__ __PRETTY_FUNCTION__); }))
# 7 "assert.c"
            ;

  printf("i=%d\n", i);

  return 0;
}
((void) sizeof (( i>0 ) ? 1 : 0), 
    __extension__ (
      { 
        if ( i>0 ) 
        ; 
        else __assert_fail ( "i>0" , "assert.c", 7, __extension__ __PRETTY_FUNCTION__);
      }
    )
);

sizeof(1 or 0)等于同sizeof(int),这句没有什么实际意义,最终编译结果中这句会被忽略丢弃并不产生任何指令操作。

GCC对ANSI C标准进行了扩展,使用这些扩展时,编译器会抛出警告。使用__extension__关键字告诉GCC不要抛出警告。


assert_NODEBUG.E

...
# 4 "assert.c"
int main(int argc, char* argv[])
{
  int i = 1;
  
# 7 "assert.c" 3 4
 ((void) (0))
# 7 "assert.c"
            ;

  printf("i=%d\n", i);

  return 0;
}

assert函数其实是一个宏,它只在DEBUG编译模式下有效。

assert 的作用是现计算表达式,如果其值为假(即为0),那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行。

使用 assert 的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。