Различное поведение компиляторов с внешней компоновкой

Когда я компилирую следующие исходные коды в VC++ 10, i со статической связью назначается 42, но в G++ 4.5.1 i с внешней связью в source2.cpp назначается 42.

Любые идеи о том, что должно быть стандартным подтверждающим поведением в соответствии со Стандартом или почему?

// source1.cpp

#include <iostream>

static int i = 0;

int h();
void foo()
{
     int i;
     {
         extern int i;
         i = 42;
     }
}

int main()
{
    foo();

    std::cout << i << std::endl;
    std::cout << h() << std::endl;
}

// source2.cpp

int i;
int h() { return i; }

person cpx    schedule 26.11.2011    source источник
comment
Как так вы знаете значение. Я не вижу никаких операторов печати.   -  person Martin York    schedule 27.11.2011
comment
+1 Ссылка на вопрос, вдохновляющий на этот вопрос: stackoverflow.com/questions/8235870/no-linkage-at-block-scope/   -  person sehe    schedule 27.11.2011
comment
я не совсем уверен, если я последую за тобой, чего ты ожидаешь?   -  person AndersK    schedule 27.11.2011
comment
gcc 4.6.1, кажется, работает, я удивлен, что gcc 4.5.1 не работает для вас.   -  person CB Bailey    schedule 27.11.2011
comment
Обновлены и добавлены операторы печати   -  person cpx    schedule 27.11.2011
comment
Я думаю, что вам не хватает некоторых #include в вашем обновлении.   -  person CB Bailey    schedule 27.11.2011
comment
Безопасно ли отвечать на этот вариант вопроса или вы планируете снова переместить ворота?   -  person CB Bailey    schedule 27.11.2011


Ответы (1)


ИСО/МЭК 14882:2011 3.5/6:

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

Внутри внутреннего блока в foo() объявление int i; скрывает объявление в области глобального пространства имен: static int i;, поэтому внутри внутреннего блока нет видимого i со связью. Это означает, что extern int i; относится к объекту с внешней связью в пространстве имен, непосредственно охватывающем foo().

Назначение должно влиять на i с внешней связью (определено в source2.cpp), оно не должно влиять на i с внутренней связью, определенной в source1.cpp.

person CB Bailey    schedule 26.11.2011