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

Когато компилирам следните източници на 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)


ISO/IEC 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