__func__ 在函数定义外部

22

如果我们在C(C99 / C11)和C ++中的函数外部使用预定义变量__func__,会发生什么?

#include <stdio.h>

const char* str = __func__;

int main(void)
{
   printf("%s", str);
   return 0;
}

仅在启用-Wall -W -pedantic选项时,gcc 4.7.2只会发出警告而不打印任何内容。

标准并没有明确说明:

ISO/IEC 14882:2011

8.4.1 一般情况 [dcl.fct.def.general]

8 函数局部预定义变量__func__的定义效果就好像提供了一个形式为static const char __func__[] = "function-name";的定义,其中function-name是一个实现定义的字符串。未指定此类变量是否具有与程序中任何其他对象不同的地址。

ISO/IEC 9899:2011

6.4.2.2 预定义标识符

1 标识符__func__应被编译器隐式声明,好像在每个函数定义的左括号后面紧跟着出现了声明static const char __func__[] = "function-name";,其中function-name是包围该标识符的函数的名称。

UB?错误?还是其他什么东西?


1
我支持错误,因为你的引语中出现了“函数本地预定义变量”和“紧随每个函数定义的左花括号后立即出现”的措辞。 - jpalecek
9
任何标准未定义的行为都是未定义行为。;) - Oliver Charlesworth
2个回答

24

标准并没有明确说明这一点

这意味着未定义行为。

根据C标准(我强调):

(C99, 4.p2) "如果在约束之外出现的“shall”或“shall not”要求被违反,则行为是未定义的。本国际标准中的“未定义行为”用“未定义行为”的字眼或未明确定义行为来表示。这三种强调方式没有差别,它们都描述了“未定义行为”."


7
(从早期的评论中提升而来) __func__处于保留命名空间中,因此实现允许在命名空间范围内将其用于任何目的。即,实现不需要对函数外部的__func__的(误)使用进行诊断,因为标准中没有禁止实现将__func__定义为char数组的命名空间范围,如果实现人员想这样做。
它可能未定义,也可能被定义为字符串或其他任何内容,并且该实现仍符合规范。
因此,在函数外部尝试使用它是未定义的行为,因为它可能已定义,也可能未定义,并且可能未正确类型以便可用。
至于问题中的代码在符合规范的实现中如何具有未定义行为的具体示例,则我认为一个实现可以将其定义为nullptr(因此示例会在printf中崩溃),甚至可以将其定义为扩展到空指针解引用的宏,然后在每个函数进入时#undef它,并在每个函数后面#define它(因此在main开始之前示例将崩溃!)

1
请提供详细的解释,而不是仅仅引用学究式的引文。 - l4rmbr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接