C语言的断言库的两种断言方式

assert.h头文件支持的断言库是一个用于辅助调试程序的小型库。它由assert()宏组成,接受一个整型表达式作为参数。如果表达式求值为假(非零),assert()宏就在标准错误流(stderr)中写入一条错误信息,并调用abort()函数终止程序(abort()函数的原型在stdlib.h头文件中)。assert()宏是为了标识出程序中某些条件为真的关键位置,如果其中的一个具体条件为假,就用assert()语句终止程序。通常,assert()的参数是一个条件表达式或逻辑表达式。如果assert()中止了程序,它首先会显示失败的测试、包含测试的文件名和行号。

1 assert的用法

程序assert.c演示了一个使用assert的小程序。在求平方根之前,该程序断言z是否大于或 等于0。程序还错误地减去一个值而不是加上一个值,故意让z得到不合适的值。

The assert.c Program

/* assert.c -- use assert() */
#include 
#include 
#include 
int main()
{
    double x, y, z;

    puts("Enter a pair of numbers (0 0 to quit): ");
    while (scanf("%lf%lf", &x, &y) == 2
                && (x != 0 || y != 0))
    {
        z = x * x - y * y;  /* should be + */
        assert(z >= 0);
        printf("answer is %fn", sqrt(z));
        puts("Next pair of numbers: ");
    }
    puts("Done");
​
    return 0;
}
​
​

下面是该程序的运行示例:

Enter a pair of numbers (0 0 to quit):
4 3
answer is 2.645751
Next pair of numbers:
5 3
answer is 4.000000
Next pair of numbers:
3 5
Assertion failed: (z >= 0), function main, file /Users/assert.c, line 14.

具体的错误提示因编译器而异。让人困惑的是,这条消息可能不是指明z >= 0,而是指明没有满足z >= 0的条件。用if语句也能完成类似的任务:

if (z < 0)
{
    puts("z less than 0");
    abort();
}

但是,使用assert()有几个好处:它不仅能自动标识文件和出问题的行号,还有一种无需更改代码就能开启或关闭assert()的机制。如果认为已经排除了程序的bug,就可以把下面的宏定义写在包含assert.h的位置前面:

#define NDEBUG

并重新编译程序,这样编译器就会禁用文件中的所有assert()语句。如果程序又出现问题,可以移除这条#define指令(或者把它注释掉),然后重新编译程序,这样就重新启用了assert()语句。

2 Staticassert(C11)

assert()表达式是在运行时进行检查。C11新增了一个特性:Staticassert声明,可以在编译时检查assert()表达式。因此,assert()会导致正在运行的程序中止,而Staticassert()会导致程序无法通过编译。Staticassert()接受两个参数。第1个参数是整型常量表达式,第2个参数是一个字符串。如果第1个表达式求值为0(或False),编译器会显示字符串,而且不编译该程序。看看程序statasrt.c的小程序,然后查看assert()和Staticassert()的区别。

The statasrt.c Program

//  statasrt.c
#include 
#include 
_Static_assert(CHAR_BIT == 16, "16-bit char falsely assumed");
int main(void)
{
    puts("char is 16 bits.");
    return 0;
}

下面是在命令行编译的示例:

$ clang statasrt.c statasrt.c:4:1: error: staticassert failed "16-bit char falsely assumed" Staticassert(CHARBIT == 16, "16-bit char falsely assumed"); ^ ~~~~~~ 1 error generated. $

根据语法,Staticassert()被视为声明。因此,它可以出现在函数中,或者在这种情况下出现在函数的外部。 Staticassert要求它的第1个参数是整型常量表达式,这保证了能在编译期求值(sizeof表达式被视为整型常量)。不能用程序清单16.18中的assert代替Staticassert,因为assert中作为测试表达式的z > 0不是常量表达式,要到程序运行时才求值。当然,可以在程序清单16.19的main()函数中使用assert(CHARBIT ==16),但这会在编译和运行程序后才生成一条错误信息,很没效率。

展开阅读全文

页面更新:2024-03-15

标签:断言   行号   平方根   常量   编译器   表达式   原型   示例   语句   函数   条件   错误   参数   语言   方式

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top