2015-04-27 1 views
13
C++

[basic.link]/6не может понять декларацию # 3 в примере [basic.link]/6 14

Имя функции, объявленной в блоке области применения и имя переменной , объявленной областью блока extern, имеет связь. Если есть видна декларации субъекта с связью, имеющей же именем и типа, игнорируя объекты, объявленных вне внутреннего ограждающих области пространства имен, декларация блока-сферы заявляет, что же сущность и получает связь предыдущей декларации , Если существует более одного такого совпадающего объекта, программа плохо сформирована. В противном случае, если ни один соответствующий объект не найден, то блок сфера объект получает внешнее связывание [Пример:.

static void f(); 
static int i = 0; // #1 
void g() { 
    extern void f(); // internal linkage 
    int i; // #2 i has no linkage 
    { 
     extern void f(); // internal linkage 
     extern int i; // #3 external linkage 
    } 
} 

Есть три объекта, названные i в этой программе. Объект с внутренней связью, введенный декларацией в глобальном масштабе (строка # 1), объект с автоматической продолжительностью хранения и отсутствие привязки, введенный декларацией в строке # 2, и объект с статическим временем хранения и внешней связью, введенный объявление в строке №3. -end пример]

У меня есть два замечания по поводу этого пункта:

  1. static int i = 0; декларация в глобальном масштабе является не видна внутри блока, содержащего декларацию extern int i; (# 3). Поэтому мы можем только сказать, что эта последняя декларация имеет внешнюю связь, т. Е. Мы не можем связать ее с объявлением # 1.
  2. В противном случае, если декларация static int i; считается видимой декларацией № 3, чем в соответствии с текстом в абзаце, объявление области блока объявляет одну и ту же сущность и получает связь с предыдущей декларацией, то есть внутреннюю связь, а не внешнюю связь, как указано в примере.

Что мне здесь не хватает?

ответ

9

Это зависит от active issue 426, который говорит:

Пример в 3.5 [basic.link] пункт 6 создает два файла-сфера переменные с тем же именем, один с внутренней связью и один с внешней ,

static void f(); 
static int i = 0;      //1 
void g() { 
     extern void f();    // internal linkage 
     int i;       //2: i has no linkage 
     { 
       extern void f();  // internal linkage 
       extern int i;   //3: external linkage 
     } 
} 

Это действительно то, что мы хотим? C99 имеет 6.2.2.7/7, что дает неопределенное поведение для отображения идентификатора с внутренней и внешней связью в одной и той же единице перевода. На C++, похоже, нет эквивалента .

Первоначальное предложение было сделать это неопределенное поведение:

Мы согласны с тем, что это ошибка.Мы предлагаем оставить этот пример, но изменить комментарий, чтобы указать, что строка // 3 имеет неопределенное поведение, и в другом месте добавляют нормативное правило, дающее такой случай неопределенным поведение.

но последние два комментария говорят:

Согласно 3.5 [basic.link] в пункте 9, две переменные с связи в предложенном примере, не являются «тот же объект», потому что они не имеют такой же связи. Некоторая другая формулировка будет необходима для , описывающей взаимосвязь между этими двумя переменными.

и:

РГС решил, что было бы лучше, чтобы сделать программу с этим рода связи несоответствия плохо образованным вместо того, чтобы неопределенное поведения.

Последние комментарии не предлагали новую формулировку, и она не обновлялась с 2006 года, поэтому в лучшем случае мы можем сказать, что нынешнее мышление состоит в том, что это плохо сформировано.

Для справки проект С99 стандарт 6.2.2.7/7 говорит:

Если в единице трансляции, тот же самый идентификатор появляется с внутренней и внешней связи, поведение не определено.

Смежные вопросы