我正在尝试在C89标准中实现我自己的assert
宏。
我希望它和最初的一样:
dir/file.c:20: MyFunction: Assertion `null != pointer` failed.
有两个问题:
- 没有打印函数名称的选项,因为预标识符
__FUNC__
仅在c99标准之后才可用 - 我不知道如何退出这个程序。我尝试了
exit(1)
和__Exit(1)
,但它们都不起作用,我认为这是因为macros
在每个处理阶段都转换为代码,这意味着预处理器甚至还不知道这些exit
函数是什么。因为它们只在编译器阶段相关,对吧
这是我的代码:
/********************************* 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
,而不是像原始assert
那样打印dir/file.c
。为什么?
我希望我能写这样的东西:
#define ASSERT(expr)
if (!(expr)){
fprintf(stderr, "%s:%d: %s: Assertion `%s` failed.n"
,__FILE__, __LINE__, __FUNC__, #expr); exit(1) }
谢谢。
-
事实上,C89没有获得函数名称的方法。因此,如果你只能依靠C89,你就不得不放弃它。注意,甚至在C99之前,许多实现可能已经为此提供了它们自己的扩展,并且可能已经在它们自己的
assert()
定义中使用了这些扩展;例如GCC具有CCD_ 13。 -
如果断言失败,标准
assert()
宏将调用abort()
。因此,如果你想复制它的行为,你也可以这样做。
Nate Eldredge回答了您的大部分查询。作为对你的P.S.的回应,我怀疑编译器可以在内部做一些我们不能做的事情。与函数名相同,但没有__func__
(尽管GCC有一个可以使用的__FUNCTION__
宏(。
不过,您仍然可以使assert
更接近编译器assert
。assert
试图尽可能最好地模拟一个函数。因此,首先,它必须作为一个表达式来工作,而您的表达式由于if
而不能工作。此外,它应该返回void
。CCD_ 24上的CCD_;原型":
void assert(scalar expression);
这两者都有可能。这是我刚刚制作的assert
,它(我认为(能够满足这两个要求:
#define ASSERT(expr)
((expr) ?
(void) 0 :
(void) (fprintf(stderr, "%s:%d: %s: Assertion `%s` failedn",
__FILE__, __LINE__, __FUNCTION__, #expr), abort()))
这利用了__FUNCTION__
GCC扩展,如果你想的话,你可以删除它。