将 __func__ 视为字符串文字而不是预定义的标识符 [英] Treating __func__ as a string literal instead of a predefined identifier

查看:18
本文介绍了将 __func__ 视为字符串文字而不是预定义的标识符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using gcc to compile C99 code. I want to write a macro which will return a string containing the function name and line number.

这就是我所拥有的:

#define INFO_MSG  __FILE__ ":"__func__"()"

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

However, when I compile code which attempts to use this string, for example:

char buff[256] = {''}
sprintf(buff, "Something bad happened here: %s, at line: %d", INFO_MSG, __LINE__);
printf("INFO: %s
", buff);

我收到以下错误消息:

error: expected ‘)’ before ‘__func__’

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

I have tracked the problem down to the macro. as when I remove __func__ from the macro, the code compiles correctly.

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

How do I fix the macro, so that I can include the predefined __func__ macro in my string?

推荐答案

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

Judging from your comments, the objective is to have a macro which combines the file name and function name (and maybe line number) into a single string that can be passed as an argument to functions such as printf() or strcpy() or syslog().

很遗憾,我认为这是不可能的.

Unfortunately, I don't think that's possible.

C11 标准说:

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

ISO/IEC 9899:2011 §6.4.2.2 Predefined identifiers

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

¶1 The identifier __func__ shall be implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration

static const char __func__[] = "function-name";

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

appeared, where function-name is the name of the lexically-enclosing function.

因此,与 __FILE____LINE__ 不同,__func__ 不是宏.

Therefore, __func__ is not a macro, unlike __FILE__ or __LINE__.

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

The related question What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__? covers some alternative names. These are GCC-specific extensions, not standard names. Moreover, the GCC 4.8.1 documentation says:

这些标识符不是预处理器宏.在 GCC 3.3 及更早版本中,仅在 C 中,__FUNCTION____PRETTY_FUNCTION__ 被视为字符串文字;它们可以被使用初始化 char 数组,它们可以与其他字符串文字连接.海合会3.4 及更高版本将它们视为变量,如 __func__.在 C++ 中,__FUNCTION____PRETTY_FUNCTION__ 一直是变量.

These identifiers are not preprocessor macros. In GCC 3.3 and earlier, in C only, __FUNCTION__ and __PRETTY_FUNCTION__ were treated as string literals; they could be used to initialize char arrays, and they could be concatenated with other string literals. GCC 3.4 and later treat them as variables, like __func__. In C++, __FUNCTION__ and __PRETTY_FUNCTION__ have always been variables.

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

There are sound reasons why these cannot be preprocessor constructs. The preprocessor does not know what a function is and whether the text it is processing is in the scope of a function, or what the name of the enclosing function is. It is a simple text processor, not a compiler. Clearly, it would be possible to build that much understanding into the preprocessor (solely for the support of this one feature), but it is not required by the standard, and neither should it be required by the standard.

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

Unfortunately, though, I think it means that attempts to combine __func__ (by any spelling) with __FILE__ and __LINE__ in a single macro to generate a single string literal are doomed.

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

Clearly, you can generate the file name and line number as a string using the standard two-step macro mechanism:

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

#define FILE_LINE __FILE__ ":" STRINGIFY(__LINE__)

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

You can't get the function name into that as part of a string literal, though.

有参数认为文件名和行号足以确定问题所在;函数名几乎没有必要.它更美观多于功能,对程序员有一点帮助,但对其他用户没有帮助.

There are arguments that the file name and line number are sufficient to identify where the problem is; the function name is barely necessary. It is more cosmetic than functional, and slightly helps programmers but not other users.

这篇关于将 __func__ 视为字符串文字而不是预定义的标识符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆