Подтвердить что ты не робот

__func__ определение внешней функции

Что произойдет, если мы используем предопределенную переменную __func__ вне функции в C (C99/C11) и С++?

#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 Локальная предопределенная переменная __func__ определяется как если бы определение формы static const char __func__[] = "function-name";, где имя функции является определяемой реализацией строка. Не указано, имеет ли такая переменная адрес отличной от функции любого другого объекта в программе.

ISO/IEC 9899: 2011

6.4.2.2 Предопределенные идентификаторы

1 Идентификатор __func__ должен быть неявно объявлен переводчиком так, как будто, немедленно после открытия скобки каждого определения функции, декларация static const char __func__[] = "function-name";появился, где function-name - это имя лексически-охватывающего функция.

UB? Ошибка? Или что-то еще?

4b9b3361

Ответ 1

Стандарт ничего не говорит об этом явно

Это означает поведение undefined.

Из стандарта C (ударный удар):

(C99, 4.p2) "Если" a "или" не будет требовать, чтобы внешнее ограничение было нарушено, поведение undefined. undefined поведение иначе указано в настоящем стандарте слова "undefined поведение или упущение какого-либо явного определения поведения. Нет никакой разницы в акценте среди этих трех: все они описывают поведение" undefined ".

Ответ 2

(продвигается из более раннего комментария)

__func__ находится в зарезервированном пространстве имен, поэтому реализации разрешено использовать его в области пространства имен для любой цели, то есть реализация не требуется для диагностики (неправильного) использования __func__ вне функции, потому что ничего в стандарте запрещает реализацию от определения __func__ в качестве массива области пространства имен char, если это то, что хотят сделать разработчики.

Это может быть undefined, или его можно определить как строку или как что-либо еще, и эта реализация по-прежнему соответствует.

Таким образом, поведение undefined пытается использовать его вне функции, потому что оно может или не может быть определено и может быть или не быть подходящим типом для использования.

Для конкретных примеров того, как код в вопросе мог иметь поведение undefined при использовании с соответствующей реализацией, я полагаю, что реализация могла бы определить его на nullptr (так что пример потерпит крах в printf) или может даже определите его макросу, который расширяется до разыменования нулевого указателя, а затем #undef он при входе каждой функции и #define после каждой функции (так что пример потерпит крах до начала main!)