如何为多行宏调用获取宏名称 __LINE__?

Posted

技术标签:

【中文标题】如何为多行宏调用获取宏名称 __LINE__?【英文标题】:How to get macro name __LINE__ for a multi-line macro call? 【发布时间】:2012-11-09 18:25:57 【问题描述】:

我创建了一个用于错误跟踪的宏。 这是一个简化的版本:

#include <stdio.h>

#define ERR(...)                                 \
    printf("error @ %d\n", __LINE__)

int main()

    return ERR(1,               /* line 7 */
               2,               /* line 8 */
               3);              /* line 10 */

执行时会打印:

error @ 10

但是,要将打印的行号与 grep 输出 (grep -n ERR test.c) 匹配,我需要 ERR 字符串的行号 (line 7)。

这样的事情可能吗?有什么想法吗?

补充说明: 宏应该看起来像一个函数调用(所以我可以做return ERR(...);)。 编译器是 GCC 版本 4.4.5。可以使用 C99 + GNU 扩展。

【问题讨论】:

【参考方案1】:

基于@cwyang 命题,在定义和逗号运算符中使用括号不匹配的宏。

#define ERR (LINEINFO, HANDLEARGS
#define HANDLEARGS(...) __LINE__)
#define LINEINFO printf("error @ %d: ", __LINE_)

return ERR(x,
           y,
           z);

将扩展到

return (printf("error @ %d: ", 5), 7);

使用 gcc。

【讨论】:

这似乎可以满足我的需求。谢谢! 哦,C 预处理器的乐趣。 哦,你好 5 年前的我。【参考方案2】:

也许这是一个选项?

#define ERR(line,...)             \
    printf("error @ %d\n", line)

ERR(__LINE__
    blah,
    blah,
    blah);

【讨论】:

(简单/理智的解决方案是根本不使用可变参数宏) 在非简化版本中,变量参数宏用于错误打印——它们无法避免。 不希望将__LINE__s 写在所有地方(无论ERR 宏在哪里)。宏应尽可能少地使用参数。 @Lundin,我看不出这与变量参数宏有什么关系。 @AProgrammer 如果宏有一个参数或没有参数,那么不同的行格式设置是不可能的。【参考方案3】:

以下内容如何:

#define VOID_MACRO(...) (void) 0
#define ERR printf("err @ %d\n", __LINE__); VOID_MACRO

【讨论】:

它有一个问题:当ERR 用作return 值时,永远不会调用VOID_MACRO(请参阅问题中的附加说明)。然而,它应该总是被调用——有一些使用可变参数的功能(在我的简化示例中没有显示)。 这部分解决了返回#define ARG_MACRO(...) returns1_and_processes_args(__VA_ARGS__) #define ERR printf("error @ %d: ", __LINE__) * ARG_MACRO的问题。然而,这并不是一个完美的解决方案。

以上是关于如何为多行宏调用获取宏名称 __LINE__?的主要内容,如果未能解决你的问题,请参考以下文章

预定义宏,C语言预定义的宏详解

Verilog 参数化宏用法

Grafana - 如何为 Mysql 数据源创建 sql 查询部分变量/宏

如何为 Solaris 和 HP-AIX 定义 _FILE_OFFSET_BITS 和 _LARGE_FILES 宏

宏表达式与函数#undef条件编译

如何为函数替换 __str__