Что должно произойти, если мы используем предопределенную переменную __func__
вне функции в C (C99 / C11) и C ++?
#include <stdio.h>
const char* str = __func__;
int main(void)
{
printf("%s", str);
return 0;
}
gcc 4.7.2 только выдает предупреждение (с -Wall -W -pedantic
включен) и ничего не печатает.
Стандарт ничего не говорит об этом явно:
ISO / IEC 14882: 2011
8.4.1 В целом [dcl.fct.def.general]
8 Предопределенная переменная local-function
__func__
определяется как если бы
определение формыstatic const char __func__[] = "function-name";
было предоставлено, где имя-функции определяется реализацией
строка. Не указано, имеет ли такая переменная адрес
отличается от любого другого объекта в программе.
ISO / IEC 9899: 2011
6.4.2.2 Предопределенные идентификаторы
1 Идентификатор
__func__
неявно объявляется переводчиком, как если бы, немедленно
после открывающей скобки каждого определения функции
декларацияstatic const char __func__[] = "function-name";
где имя-функции — это имя лексически-вмещающего
функция.
UB? Ошибка? Или что-то другое?
Стандарт ничего не говорит об этом явно
Это означает неопределенное поведение.
Из стандарта С (выделено мое):
(C99, 4.p2) «Если требование » должен » или » не должен »», которое появляется вне ограничения, нарушается, поведение не определено. Неопределенное поведение иначе указано в этом международном стандарте словами » «неопределенное поведение» или отсутствием какого-либо явного определения поведения. Нет разницы в акценте между этими тремя; все они описывают «поведение, которое не определено» «.
(Повышено из более раннего комментария)
__func__
находится в зарезервированном пространстве имен, поэтому реализации разрешается использовать его в области имен для любых целей, т. е. реализация не требуется для диагностики (неправильного) использования __func__
вне функции, потому что ничто в стандарте не запрещает реализации определять __func__
в виде массива пространства имен char
если это то, что разработчики хотят сделать.
Это может быть неопределенным, или это может быть определено как строка, или как что-либо еще, и эта реализация все еще соответствует.
Так что это неопределенное поведение — пытаться использовать его вне функции, потому что оно может или не может быть определено, и может иметь или не иметь правильный тип для использования.
Для конкретных примеров того, как код в вопросе может иметь неопределенное поведение при использовании с соответствующей реализацией, я полагаю, что реализация может определить его следующим образом: nullptr
(таким образом, в примере printf
) или может даже определить его в макрос, который расширяется до разыменования нулевого указателя, а затем #undef
это при входе в каждую функцию и #define
это после каждой функции (так что пример будет падать до main
начинается!)