C陷阱与缺陷 第6章 预处理器 6.3 宏并不是语句

本文探讨了C语言中assert宏的使用,用于在程序运行时检查条件是否满足。当条件不成立时,assert宏会终止程序并提供错误信息。文章分析了在宏定义中遇到的问题,如语句结构混乱和语法错误,并提出了相应的解决方案,包括使用大括号包围宏体和利用短路运算符避免不必要的函数调用。此外,还展示了如何通过巧妙的宏定义来确保assert在语句中的正确使用,同时保持代码的清晰性和效率。
摘要由CSDN通过智能技术生成

    assert宏,它的参数是一个表达式,如果该表达式为0,就使程序终止执行,并给出一条适当的出错信息。把assert作为宏来处理,这样就使得我们可以在出错信息中包含文件名和断言失败处的行号。也就是说, 
    assert(x > y);
    在x大于y时什么也不做,在其他情况下则会终止程序。
    第一次尝试: 
    #define assert(e) if (!e) assert_error(__FILE__, __LINE__)
    因为考虑到宏assert的使用人员会加上一个分号,所以在宏定义中并没有包括分号。
    __FILE__和__LINE__是内建于C语言处理器中的宏,它们会扩展为所在文件的文件名和所处代码行的行号。 

    if (x > 0 && y > 0) 
        assert(x > y);
    else 
        assert(y > x);

    上面例子的展开形式: 
    if (x > 0 && y > 0) 
        if (!(x > y)) assert_error("foo.c", 37);
    else 
        if (!(y > x)) assert_error("foo.c", 39);
    将上面的代码做适当的缩排处理,我们就能够看清它实际的流程结构与我们期望的结构有怎样的区别:
    if (x > 0 && y > 0) 
        if (!(x > y))
            assert_error("foo.c", 37);
        else 
            if (!(y > x))
                assert_error("foo.c", 39);
    在宏assert的定义中用大括号把宏整个给括起来,就能避免这样的问题产生: 
    #define assert(e) \
    {
        if (!e) assert_error(__FILE__, __LINE__); 
    }
    这个又带来了新的问题: 
    if (x > 0 && y > 0) 
    {
            if (!(x > y)) assert_error(__FILE__, __LINE__);
    };
    else 
    {
        if (!(x > y)) assert_error(__FILE__, __LINE__);
    };
    在else之前的分号是一个语法错误。要解决这个问题,一个办法是对assert的调用在后面不再跟
一个分号,但这样的用法显得有些“怪异”: 
    y = distance(p, q);
    assert(y > 0)
    x = sqrt(y);
    这个定义看起来像一个表达式,不是类似于一个语句 
    #define assert(e) ((void)((e) || _assert_error(__FILE__, __LINE__)))
    这个定义实际上利用了||运算符对两侧的操作数依次顺序求值的性质。如果e为true(真),表达式 
    (void)((e) || _assert_error(__FILE__, __LINE__))
的值没有求出其右侧表达式 
    _assert_error(__FILE__, __LINE__)
的值的情况下就可以确定最终的结果为真。如果e为false(假),右侧表达式 
    _assert_error(__FILE__, __LINE__)
的值必须求出,此时_assert_error将被调用,并打印出一条恰当的“断言失败”的出错消息。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_40186813

你的能量无可限量。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值