将__func__视为字符串文字而不是预定义的标识符

Hom*_*lli 15 c macros

我正在使用gcc编译C99代码.我想写一个宏,它将返回一个包含函数名和行号的字符串.

这就是我所拥有的:

#define INFO_MSG  __FILE__ ":"__func__"()"
Run Code Online (Sandbox Code Playgroud)

但是,当我编译试图使用此字符串的代码时,例如:

char buff[256] = {'\0'}
sprintf(buff, "Something bad happened here: %s, at line: %d", INFO_MSG, __LINE__);
printf("INFO: %s\n", buff);
Run Code Online (Sandbox Code Playgroud)

我收到以下错误消息:

error: expected ‘)’ before ‘__func__’
Run Code Online (Sandbox Code Playgroud)

我已将问题跟踪到宏.当我__func__从宏中删除时,代码正确编译.

如何修复宏,以便我可以__func__在我的字符串中包含预定义的宏?

Jon*_*ler 21

从你的评论来看,目标是有一个宏,它将文件名和函数名(以及行号)组合成一个字符串,可以作为参数传递给printf()or strcpy()syslog().等函数.

不幸的是,我不认为这是可能的.

C11标准说:

ISO/IEC 9899:2011§6.4.2.2 预定义标识符

1标识符__func__应由翻译者隐式声明,就像紧跟在每个函数定义的左括号之后的声明一样

static const char __func__[] = "function-name";
Run Code Online (Sandbox Code Playgroud)

出现了,其中function-name是词法封闭函数的名称.

因此,__func__不是__FILE__或不是宏__LINE__.

相关问题有什么之间的区别__PRETTY_FUNCTION__,__FUNCTION__,__func__涵盖一些替代名称.这些是GCC特定的扩展,而不是标准名称.此外,GCC 4.8.1文档说:

这些标识符不是预处理器宏.在GCC 3.3和更早,在C只,__FUNCTION__并且__PRETTY_FUNCTION__被视为字符串文字; 它们可以用于初始化char数组,并且可以与其他字符串文字连接.GCC 3.4及更高版本将它们视为变量,如__func__.在C++中,__FUNCTION__并且__PRETTY_FUNCTION__一直都有变数.

有充分理由说明为什么这些不能成为预处理器结构.预处理器不知道函数是什么以及它正在处理的文本是否在函数的范围内,或者封闭函数的名称是什么.它是一个简单的文本处理器,而不是编译器.显然,可以在预处理器中建立这么多的理解(仅用于支持这一特性),但标准并不要求它,标准也不需要它.

但不幸的是,我认为,这意味着,试图结合__func__(通过任何拼写)与__FILE____LINE__在一个宏生成一个字符串字面注定.

显然,您可以使用标准的两步宏机制将文件名和行号生成为字符串:

#define STR(x) #x
#define STRINGIFY(x) STR(x)

#define FILE_LINE __FILE__ ":" STRINGIFY(__LINE__)
Run Code Online (Sandbox Code Playgroud)

但是,您无法将函数名称作为字符串文字的一部分.

有些论点认为文件名和行号足以确定问题所在; 功能名称几乎是不必要的.它比化妆品更具外观,并且对程序员有所帮助,但对其他用户没有帮助.