为什么断言是宏而不是函数? [英] Why is assert a macro and not a function?

查看:25
本文介绍了为什么断言是宏而不是函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的讲师在课堂上问过我这个问题,我想知道为什么它是一个宏而不是一个函数?

My lecturer has asked me that in class, and I was wondering why is it a macro instead of a function?

推荐答案

简单的解释是标准要求 assert 是一个宏,如果我们看一下 C99 标准草案(据我所知,各部分在草案C11标准中也是一样的) 部分 7.2 Diagnostics 2 说:

The simple explanation would be that the standard requires assert to be a macro, if we look at the draft C99 standard(as far as I can tell the sections are the same in draft C11 standard as well) section 7.2 Diagnostics paragraph 2 says:

assert 宏应该作为一个宏来实现,而不是作为一个实际的功能.如果宏定义被抑制以访问实际功能,行为未定义.

The assert macro shall be implemented as a macro, not as an actual function. If the macro definition is suppressed in order to access an actual function, the behavior is undefined.

为什么需要这个,中给出的理由国际标准——编程语言——C 的基本原理是:

Why does it require this, the rationale given in Rationale for International Standard—Programming Languages—C is:

使断言成为真正的函数可能很困难或不可能,因此仅限于宏形式.

It can be difficult or impossible to make assert a true function, so it is restricted to macro form.

这不是很有用,但我们可以从其他要求中看出原因.回到 7.21 说:

which is not very informative, but we can see from other requirements why. Going back to section 7.2 paragraph 1 says:

[...]如果 NDEBUG 在源文件中被定义为宏名其中包括,断言宏简单地定义为

[...]If NDEBUG is defined as a macro name at the point in the source file where is included, the assert macro is defined simply as

#define assert(ignore) ((void)0)

assert宏根据NDEBUG的当前状态重新定义每次都包含在内.

The assert macro is redefined according to the current state of NDEBUG each time that is included.

这很重要,因为它使我们可以轻松地在发布模式下关闭断言,在这种模式下,您可能希望承担可能昂贵的检查成本.

This is important since it allows us an easy way to turn off assertions in release mode where you may want to take the cost of potentially expensive checks.

第二个重要要求是需要使用宏__FILE____LINE____func__,这在7.2.1.1 assert 宏,它说:

and the second important requirement is that it is required to use the macros __FILE__, __LINE__ and __func__, which is covered in section 7.2.1.1 The assert macro which says:

[...] 断言宏写入有关特定调用的信息失败的 [...] 后者分别是预处理宏 __FILE_ _ 和 __LINE_ _ 以及标识符__func__) 以实现定义的格式在标准错误流上执行.165) 然后调用 abort 函数.

[...] the assert macro writes information about the particular call that failed [...] the latter are respectively the values of the preprocessing macros __FILE_ _ and __LINE_ _ and of the identifier __func_ _) on the standard error stream in an implementation-defined format.165) It then calls the abort function.

其中脚注 165 说:

写的消息可能是以下形式:

The message written might be of the form:

Assertion failed: expression, function abc, file xyz, line nnn.

将其作为宏允许宏 __FILE__ 等...在适当的位置进行评估,正如 Joachim 指出的那样,宏允许它插入原始的表达式 在它生成的消息中.

Having it as a macro allows the macros __FILE__ etc... to be evaluated in the proper location and as Joachim points out being a macro allows it to insert the original expression in the message it generates.

C++ 标准草案要求 cassert 头文件的内容与标准 C 库中的 assert.h 头文件相同:

The draft C++ standard requires that the contents of the cassert header are the same as the assert.h header from Standrd C library:

内容与标准C库头文件相同.

The contents are the same as the Standard C library header .

另见:ISO C 7.2.

See also: ISO C 7.2.

为什么是 (void)0?

为什么要使用 (void)0 而不是其他什么都不做的表达式?我们可以想出几个原因,首先这是 7.2.1.1 部分中断言概要的样子:

Why use (void)0 as opposed to some other expression that does nothing? We can come up with a few reasons, first this is how the assert synopsis looks in section 7.2.1.1:

void assert(scalar expression);

它说(强调我的):

assert 宏将诊断测试放入程序中;它扩展为空表达式.

The assert macro puts diagnostic tests into programs; it expands to a void expression.

表达式(void)0 与需要以void 表达式结尾是一致的.

the expression (void)0 is consistent with the need to end up with a void expression.

假设我们没有这个要求,其他可能的表达式可能会产生不良影响,例如允许在发布模式下使用 assert 而在调试模式下不允许使用,例如使用 普通的 0 将允许我们在作业中使用 assert如果使用得当,可能会生成一个 expression result used 警告.至于使用复合语句作为注释建议,我们可以从C多行宏:do/while(0) 与作用域阻塞表明它们在某些情况下会产生不良影响.

Assuming we did not have that requirement, other possible expressions could have undesirable effects such as allowing uses of assert in release mode that would not be allowed in debug mode for example using plain 0 would allow us to use assert in an assignment and when used correctly would likely generate an expression result unused warning. As for using a compound statement as a comment suggests, we can see from C multi-line macro: do/while(0) vs scope block that they an have undesirable effects in some cases.

这篇关于为什么断言是宏而不是函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆