Xref: utzoo comp.lang.c++:5945 gnu.g++.bug:1258 Path: utzoo!utgpu!jarvis.csri.toronto.edu!clyde.concordia.ca!uunet!mcsun!ukc!dcl-cs!aber-cs!pcg From: pcg@aber-cs.UUCP (Piercarlo Grandi) Newsgroups: comp.lang.c++,gnu.g++.bug Subject: Re: bug 12178901 (1.36.1) - linkage of global const objects Summary: storage class != linkage (or not?); extern "C" is tricky, etc... Message-ID: <1545@aber-cs.UUCP> Date: 20 Dec 89 16:28:53 GMT Reply-To: pcg@cs.aber.ac.uk (Piercarlo Grandi) Distribution: gnu Organization: Dept of CS, UCW Aberystwyth (Disclaimer: my statements are purely personal) Lines: 89 Anyway, many people have now corrected me regarding the C++ default linkage for const objects. This is really being a language lawyer, but: linkage != storage class. From what I understand, const implies by default the *storage class* static; this in turn, at file scope, implies local linkage. To see the difference, consider const entities local to a block; is their default storage class "auto" or "static"? To me it is "static" in C++ (and "auto" in Ansi C), even if linkage only really makes sense at file scope level. The question is not as inane as it looks, because from it depends whether it is ok to use the address of a const object outside the block in which it is declared, something that may be actually useful. In any case, follow Peter's paternal advice: *always* specify the storage class in C++, *especially* on inlines and consts, inside and outside classes, functions, blocks. Storage classes in C and C++ are a difficult issue; for example, the Register C Compiler from AT&T, if I remember well, on the 386, will forbid the explicit use of the "auto" storage class on parameters. I think this is wrong... By the way, BUG REPORT: with GNU C++ 1.35.0, procedure parameters may be defined with storage classes "static" and "extern", which is (I reckon) not allowed, without complaint; these are ignored. The same applies when the parameters are declared in a prototype; the following compiles without problems: extern "C" extern int printf(extern const char *,...); main(extern const int argc,static char **const argv) { (void) printf("argc %d, argv %0lx\n", argc,(long unsigned) argv); return 0; } Ah, yes, by the way: GNU C++ at least does not allow parameters to have storage class 'typedef', thank goodness, but this probably means that typedef is not really handled as a storage class, because a syntax error is signaled, which is wrong, because *syntactically* typedef could well appear in any declaration; it is a *semantic* error though, just like for static and extern. Just to show off: how many of you did know that "typedef" technically is a storage class in C (and C++), and that 'extern "C"' does *not* imply the "extern" storage class, because it is not a storage class? Does it matter that 'extern "C"' is not a storage class ? YES! for example, both of these are accepted gleefully by GNU C++ (and correctly, I believe): extern "C" typedef int algebraic; /* correct, but somewhat pointless */ extern "C" static unsigned zero = 0; /* also a bit pointless */ Note that the proper way to declare an external C constant in C++ is the following: extern "C" extern const unsigned one; /* declaration, in .H */ extern "C" extern const unsigned one = 1; /* definition, in .C */ If you omit the extern from the first line, it becomes a *definition* too, and is illegal under C++ 2.0 rules, because now it is illegal to have more than one definition of a variable (contrarily to customary C practice, but wisely). Notice that since mangling does not apply to variable names yet (I am sure that eventually Stroustrup will find a way to allow overloading of variables too, :-> -- only half a joke here, consider templates), 'extern "C"' applied to variable names is not strictly necessary, but I suggest to use it nonetheless, to show that the variable is actually defined and used also by non C++ code. In other words: C++ has even worse overloading of reserved words than C, and we must suffer this, as the only way out would be either a proliferation of new reserved words, or abandoning the C type structure, both of which would make C++ very much less C compatible. I think that Ron Guilmette (I remember he being the author) has a few new/old interesting test cases to add to his fine C++ test suite... And a little more work for Michael Tiemann (God knows how cfront behaves with all this). -- Piercarlo "Peter" Grandi | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk Dept of CS, UCW Aberystwyth | UUCP: ...!mcvax!ukc!aber-cs!pcg Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk