如何避免在if上“持续表达”?

时间:2013-07-04 21:35:38

标签: c if-statement assert assertions constant-expression

我有一个assert宏,可以解析为if,如下所示:

#define assert(expr) \
if (!(expr)) \
{ \
    handle_failed_assert(); \
}

忽略handle_failed_assert()的工作原理,您无需引用do { ... } while(0)技巧。请关注这背后的功能。

现在,真正的问题来了。有时我想强迫和断言,并使其有意义。所以我们用这个:

assert(!"Assert cause carefully described.");

问题是我们有基于 RVCT 2.2 的编译器 vrxcc ,在编译时会抛出此警告:

#236-D: controlling expression is constant

当然,这会解析为编译常量if

我怎么能欺骗编译器接受呢?

1 个答案:

答案 0 :(得分:1)

你的问题最终归结为“我的编译器太聪明了,我如何让它停止抱怨某些东西,是的,是的,这通常是程序员的错误,但在这种情况下不是程序员的错误“。只有两种方法可以做到这一点:

  • 智胜编译器。这与编译器有关。
  • 告诉编译器“不要抱怨,这不是错误。”这与编译器有关。

我对vrxcc一无所知。 R的评论倾向于做第一个。这种事情几乎可以保证起作用:

extern int __truefunc(void);
#define assert(expr) ((__truefunc() && (expr)) || __assert_fail(#expr))

其中truefunc是一个总是返回1的函数,并且您可以单独编译以智能编译器。当然,成本是无用的运行时调用。

“告诉编译器”方法更好,但需要某种编译器文档辅助。


附录:我在淋浴时发现,在你的特殊情况下,你已经决定恐慌,所以你可以有一个panic功能,并在这里打电话。缺点是你必须改变所有现有的common_assert(!"some string")电话,但至少你可以机械地做到这一点。

如果语言内置了两个参数assert或作为标准内容,那可能会很好。这些天FreeBSD内核使用KASSERT,或多或少为:

#define KASSERT(expr, panic_args) \
    do { if (!(expr)) panic panic_args; } while (0)

语法上有点笨拙,但非常灵活:

KASSERT(foo.field == FOO_MAGIC,
    ("memory overwrite of foo data structure: %d != %d",
        foo.field, FOO_MAGIC));