【发布时间】:2021-05-06 14:54:51
【问题描述】:
我正在尝试在 C89 标准中实现我自己的 assert 宏。
我希望它和原来的一模一样:
dir/file.c:20: MyFunction: Assertion `null != pointer` failed.
有2个问题:
- 没有打印函数名称的选项,因为预标识符
__FUNC__仅在 c99 标准后可用。 - 我不知道如何退出程序。我尝试了
exit(1)和__Exit(1),但它们都不起作用,我认为这是因为macros在每个处理阶段被转换为代码,这意味着预处理器甚至不知道这些是什么@ 987654328@ 功能尚未。因为它们只在编译阶段相关,对吧?
这是我的代码:
/********************************* Inclusions *********************************/
#include <stdio.h> /* printf, NULL */
/***************************** Macros Definitions *****************************/
#define ASSERT(expr) \
if (!(expr)){ \
fprintf(stderr, "%s:%d: Assertion `%s` failed.\n" \
,__FILE__, __LINE__, #expr); }
/******************************************************************************/
int main()
{
void *null_ptr = NULL;
ASSERT(NULL != null_ptr);
printf("ALL WORKS");
return (0);
}
/******************************************************************************/
我的输出是:
`file.c:25: Assertion `NULL != null_ptr` failed.`
有什么方法可以获取函数名或者用宏退出程序吗? 因为现在,我没有得到函数的名称,更重要的是,即使断言打印了错误消息,程序也没有停止。
这很奇怪,因为无法获取函数名或使用宏退出程序,但原始的assert 却可以做到这两点?
P.S __FILE__ 每个标识符只为我打印文件名,就像 file.c 而不是 dir/file.c 就像原来的 assert 那样。这是为什么呢?
我希望我能写出类似的东西:
#define ASSERT(expr) \
if (!(expr)){ \
fprintf(stderr, "%s:%d: %s: Assertion `%s` failed.\n" \
,__FILE__, __LINE__, __FUNC__, #expr); exit(1) }
谢谢。
【问题讨论】:
-
如果您在宏中添加分号和
#include <stdlib.h>,则宏中的exit应该可以工作 -
预处理器不需要关心
exit()是什么意思。它只需将该函数调用放入代码中。编译器和链接器会处理它。 -
"我希望它和原版一模一样:" 什么是“原版”?你从哪里得到那个输出?还有“但他们俩都不工作”“不工作”是什么意思?会发生什么?
-
assert不需要打印函数名称。它需要以实现定义的方式打印文件名和行号以及参数的文本。然后需要调用abort(不是exit)。 -
请注意,以这种方式在宏中使用
if是错误的;如果程序员写if (cond) ASSERT(expr); else other_stuff();它不会像他们期望的那样表现。这就是需要do while hack 的原因。但是,正如@mediocrevegetable1 在他们的回答中所说,您的宏无论如何都应该扩展为表达式,因此您需要使用? :而不是if。
标签: c macros c-preprocessor assert exit