Не могу понять объявление # 3 в примере [basic.link]/6 С++ 14
[basic.link]/6
Имя функции, объявленной в области блока, и имя переменная, объявленная объявлением блока extern
, имеет связь. Если существует объявление visible объекта с привязкой, имеющей одно и то же имя и тип, игнорируя объекты, объявленные вне самой внутренней охватывающая область пространства имен, объявление области блока объявляет, что и получает связь с предыдущей декларацией. Если существует более одного такого совпадающего объекта, программа плохо сформирован. В противном случае, если соответствующий объект не найден, область действия блока объект получает внешнюю связь. [Пример:
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 пример]
У меня есть два комментария об этом абзаце:
- Объявление
static int i = 0;
в глобальной области видимости не отображается внутри блока, содержащего объявление extern int i;
(# 3). Поэтому мы можем только сказать, что это последнее объявление имеет внешнюю связь, т.е. Мы не можем связать его с объявлением № 1.
- В противном случае, если объявление
static int i;
считается видимым объявлением № 3, чем в соответствии с текстом в абзаце, объявление области блока объявляет один и тот же объект и получает связь с предыдущей декларацией, то есть внутреннюю связь, а не внешняя связь, как указано в примере.
Что мне здесь не хватает?
Ответы
Ответ 1
Это зависит от активной проблемы 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, что дает undefinedповедение для отображения идентификатора с внутренним и внешним в одной и той же переводческой единице. С++, похоже, не имеет эквивалентны.
Первоначальное предложение состояло в том, чтобы сделать его undefined:
Мы согласны с тем, что это ошибка. Мы предлагаем оставить этот пример, но измените комментарий, чтобы указать, что строка // 3 имеет поведение undefined, и в другом месте добавляют нормативное правило, дающее такой случай undefinedповедение.
но последние два комментария говорят:
Согласно пункту 3.5 [basic.link] 9, две переменные с связи в предлагаемом примере не являются "одной и той же сущностью", поскольку они не имеют такой же связи. Некоторая другая формулировка будет необходима для описать взаимосвязь между этими двумя переменными.
и
КСР решила, что было бы лучше сделать программу с этим вид несоответствия связи неправильный, а не undefinedповедение.
Последние комментарии не предлагали новую формулировку, и она не обновлялась с 2006 года, поэтому в лучшем случае мы можем сказать, что нынешнее мышление состоит в том, что это плохо сформировано.
Для справки проект стандарта C99 6.2.2.7/7
гласит:
Если в пределах единицы перевода появляется один и тот же идентификатор с внутренним и внешним связь, поведение undefined.