C89中assert宏的实现,如何退出程序?
assert macro implementation in C89, how to exit the program?
我正在尝试在 C89 标准中实现我自己的 assert
宏。
我希望它和原来的一模一样:
dir/file.c:20: MyFunction: Assertion `null != pointer` failed.
有2个问题:
- 没有打印函数名称的选项,因为预标识符
__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
而不是 dir/file.c
原始 assert
那样。这是为什么?
我希望我能写这样的东西:
#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 有 __FUNCTION__
.
标准 assert()
macro calls abort()
如果断言失败。所以如果你想复制它的行为,你也可以这样做。
Nate Eldredge 回答了您的大部分问题。作为对您 P.S. 的回应,我怀疑这是编译器可以在内部做而我们做不到的事情。与函数名称相同,但没有 __func__
(尽管 GCC 有一个 __FUNCTION__
宏,您可以使用)。
尽管如此,您仍然可以使 assert
更接近编译器 assert
。 assert
试图尽可能地模拟一个函数。因此,首先,它必须作为一个表达式来工作,而你的表达式却不能,因为 if
。此外,它应该 return void
。 man
page on assert
给出了这个“原型”:
void assert(scalar expression);
这两种都有可能。这是我刚刚制作的 assert
(我认为)设法满足这两个要求:
#define ASSERT(expr) \
((expr) ? \
(void) 0 : \
(void) (fprintf(stderr, "%s:%d: %s: Assertion `%s` failed\n", \
__FILE__, __LINE__, __FUNCTION__, #expr), abort()))
这利用了 __FUNCTION__
GCC 扩展,您可以根据需要删除它。
我正在尝试在 C89 标准中实现我自己的 assert
宏。
我希望它和原来的一模一样:
dir/file.c:20: MyFunction: Assertion `null != pointer` failed.
有2个问题:
- 没有打印函数名称的选项,因为预标识符
__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
而不是 dir/file.c
原始 assert
那样。这是为什么?
我希望我能写这样的东西:
#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 有__FUNCTION__
.标准
assert()
macro callsabort()
如果断言失败。所以如果你想复制它的行为,你也可以这样做。
Nate Eldredge 回答了您的大部分问题。作为对您 P.S. 的回应,我怀疑这是编译器可以在内部做而我们做不到的事情。与函数名称相同,但没有 __func__
(尽管 GCC 有一个 __FUNCTION__
宏,您可以使用)。
尽管如此,您仍然可以使 assert
更接近编译器 assert
。 assert
试图尽可能地模拟一个函数。因此,首先,它必须作为一个表达式来工作,而你的表达式却不能,因为 if
。此外,它应该 return void
。 man
page on assert
给出了这个“原型”:
void assert(scalar expression);
这两种都有可能。这是我刚刚制作的 assert
(我认为)设法满足这两个要求:
#define ASSERT(expr) \
((expr) ? \
(void) 0 : \
(void) (fprintf(stderr, "%s:%d: %s: Assertion `%s` failed\n", \
__FILE__, __LINE__, __FUNCTION__, #expr), abort()))
这利用了 __FUNCTION__
GCC 扩展,您可以根据需要删除它。