Łą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:
-
Najpierw
static
, potemextern
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)).
-
Najpierw
extern
, potemstatic
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.
-
Najpierw
const
, potemextern
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.
-
Najpierw
extern
, potemconst
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
Pierwsza interpretacja zauważa, że
pi1
jest zadeklarowanaconst
, ale jest również zadeklarowanaextern
. Zmienna ma więc zewnętrzne powiązanie.Druga interpretacja interpretuje oba przypadki "zadeklarowanego" w odniesieniu do tej samej deklaracji. W ten sposób oznacza to, że jest deklarowane
const
, ale nieextern const
. Zauważamy, że(e)
jest zadeklarowaneconst
, a nieextern const
, więc podajemypi1
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
.
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).
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.
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.
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