Łączenie różnych zmiennych const/statycznych

Mam kilka pytań dotyczących powiązania z następującymi zmiennymi. Na przykładach 7.1.1/7 C++03 i eksperymentując z kompilatorami (Comeau, Clang i GCC) doszedłem do następujących rodzajów linkowania:

  1. Najpierw static, potem extern

    static int a; // (a)
    extern int a; // (b) valid, 'a' still internal
    

    Jest dla mnie jasne, zgodnie z sekcją 3.5: (A) oznacza wewnętrzne powiązanie. I (b) oznacza również powiązanie wewnętrzne, ponieważ nazwa" a " jest deklarowana jako statyczna (przez (a)).

  2. Najpierw extern, potem static

    extern int b; // (c)
    static int b; // (d) invalid!
    

    Po pierwsze, (c) oznacza powiązanie zewnętrzne. Ale (d) implikuje wewnętrzne powiązanie, ponieważ nazwa " b " jest deklarowana statycznie przez (d). Jest to nieprawidłowe zgodnie z 7.1.1 / 7, ponieważ sugerowane powiązanie nie jest spójne.

  3. Najpierw const, potem extern

    const double pi1 = 3.14; // (e)
    extern const double pi1; // (f) valid and 'pi1' is internal
    

    Po pierwsze, (e) implikuje wewnętrzne powiązanie, ponieważ jest const i ani nie deklaruje wyraźnego zewnętrznego, ani wcześniej implikowanego zewnętrznego powiązania. I (f) powinna oznaczać związek zewnętrzny i być błędem, ponieważ jawnie deklaruje nazwę extern, ale Kompilatory zachowują ją wewnątrz! dlaczego tak? to moje pytanie.

  4. Najpierw extern, potem const

    extern const double pi2; // (g)
    const double pi2 = 3.14; // (h) valid and 'pi2' is external
    

    Teraz, (g) implikuje zewnętrzne powiązanie, ponieważ jawnie zadeklarowaliśmy extern. Oraz (h) implikuje również powiązanie zewnętrzne, ponieważ (g) jawnie deklaruje extern.


Eksperymentalnie znalazłem powiązanie dla 3 i 4 z następującym szablonem (wymagany jest drugi argument mieć podlinkowanie zewnętrzne)

template<typename T, T&> struct ensure { };

ensure<const double, pi1> e1; // failed
ensure<const double, pi2> e2; // succeeded

Podsumowanie: dyskusja zCharles Bailey okazała się dość owocna i pokazała, że istnieją dwie możliwe interpretacje 3.5/3, gdzie ważny punkt brzmi

Nazwa posiadająca zakres przestrzeni nazw (3.3.5) ma wewnętrzne powiązanie, jeśli jest to nazwa

  • obiekt lub odniesienie, które jest jawnie zadeklarowane const i ani jawnie zadeklarowane extern, ani poprzednio deklarowane, że mają powiązania zewnętrzne;

Jeśli spojrzymy na punkt (f), to dwie interpretacje dochodzą do różnych wniosków, jak pokazano poniżej

  1. Pierwsza interpretacja zauważa, że pi1 jest zadeklarowana const, ale jest również zadeklarowana extern. Zmienna ma więc zewnętrzne powiązanie.

  2. Druga interpretacja interpretuje oba przypadki "zadeklarowanego" w odniesieniu do tej samej deklaracji. W ten sposób oznacza to, że jest deklarowane const, ale nie extern const. Zauważamy, że (e) jest zadeklarowane const, a nie extern const, więc podajemy pi1 wewnętrzne powiązanie.

Jaka interpretacja jest poprawna? Nie mogę stwierdzić na podstawie tego sformułowania, ale Kompilatory wydają się interpretować to w drugi sposób. W szczególności, jeśli weźmiemy pierwszą interpretację, to ostatnia cytowana część 3.5/3 byłaby zbędna, ponieważ nie byłoby ważnego scenariusza, w którym nazwa byłaby deklarowana const i poprzednio deklarowane z linkiem zewnętrznym, ale bez wyraźnego extern.

Author: Community, 2010-08-22

3 answers

const double pi1 = 3.14; // (e)
extern const double pi1; // (f) valid and 'pi1' is internal
Moja interpretacja jest następująca. Rozważając powiązanie nazwy, bierzemy pod uwagę zarówno poprzednie deklaracje, jak i te interpretowane w tym momencie w parsie. Dlatego static int a; extern int a; jest OK, ale extern int b; static int b; nie jest.

Po napotkaniu pierwszej deklaracji zauważamy, że pi1 jest jawnie zadeklarowana const, ale ani jawnie zadeklarowana extern, ani wcześniej zadeklarowana jako połączenie zewnętrzne. Pasuje do jednej z opcji 3.5 / 2 dlatego pi1 ma wewnętrzne linkage.

Po napotkaniu drugiej deklaracji pytamy o pi1 nazwę obiektu, który jest jawnie zadeklarowany const, ale ani jawnie zadeklarowany extern, ani [... bla ...]. Twierdzę, że jest to spowodowane tym, że zostało to tak zadeklarowane w lit. e). Oczywiście, nie jest ona deklarowana wszędzie, ale w ten sam sposób a była nazwą obiektu zadeklarowanego static kiedy rozważaliśmy deklarację extern int a;, mimo że nie została zadeklarowana static wszędzie. To, dla mnie, oznacza, że deklaracja (f) nie oznacza innego powiązania z deklaracją (e).

 4
Author: CB Bailey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-22 00:55:37

Myślę, że w #3 popełniłeś błąd w swojej analizie. Z tego co wiem, const nie sugeruje nic o powiązaniach. Nie jestem pewien, jak doszedłeś do wniosku, że kompilator sprawia, że połączenie jest wewnętrzne. Większość kompilatorów (jako optymalizacja) zastąpi wszystkie odniesienia do zmiennej const przez wartość, na którą została zainicjowana, więc symbol może w ogóle nie pojawić się w kodzie.

A nawet jeśli nie, to z #1 wynika, że jeśli coś z wewnętrznym połączeniem jest następnie zadeklarowane za pomocą słowa kluczowego extern, że pozostaje z wewnętrznym połączeniem. Więc nie wiem, dlaczego spodziewasz się błędu.

I jeśli const implikowane połączenie wewnętrzne, to #4 powinien być błędem z tego samego powodu #2.

 0
Author: Omnifarious,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-21 21:18:51

Posiadanie zarówno (e), jak i (f) w tym samym zakresie przestrzeni nazw jest po prostu nieważne, zgodnie z §7.1.1/7 "powiązania implikowane kolejnymi deklaracjami dla danego podmiotu muszą się zgadzać.".

Ta zasada wymaga diagnostyki.

Jednak przynajmniej Comeau Online nie diagnozuje naruszenia.

Cheers & hth.,

EDIT: He he, sprawdziłem DR 426 , Jak wspomniano w innej odpowiedzi tutaj, i wydaje się, że ci, którzy opracowali projekt uchwały, czyniąc ją UB zamiast diagnozy, nie byli świadomi §7.1.1 / 7. Nie będę komentował tej sprawy ani nawet podnosił jej w komp.choroby weneryczne.c++ , ponieważ praca standaryzacyjna okazała się dla mnie zbyt polityczna i bezsensowna (bełkotliwe argumenty). Ale tak czy siak, kod jest nieważny.

 0
Author: Cheers and hth. - Alf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-29 06:13:36