On 21/01/18 08:12, Jay K wrote: > extern const int foo = 123; > > > > Why does this warn? > This is a valid portable form, with the same meaning > across all compilers, and, importantly, portably > to C and C++. > > I explicitly do not want to say: > > const int foo = 123 > > because I want the code to be valid and have the same meaning > in C and C++ (modulo name mangling). > > I end up with: > > // Workaround gcc warning. > #ifdef __cplusplus > #define EXTERN_CONST extern const > #else > #define EXTERN_CONST const > #endif > > > EXTERN_CONST int foo = 123; > > and having to explain it to people. >
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=45977> This suggests that gcc authors consider mixing "extern" and initialization to be such bad style that the compiler warns by default. But the "bug" is that there is no flag to turn off this warning. (Ideally every warning should have a matching flag, even if the warning is enabled by default.) Usually you do not want to have "extern" and initialisation in the same line - it indicates a questionable organisation of your sources which is more likely to be error-prone than the standard idioms. (I say "questionable", not necessarily wrong - but certainly I would question it if I saw it in source code.) Normally you want: // file.h // declaration, not definition extern const int foo; // file.c #include <file.h> // definition const int foo = 123; // otherfile.c #include <file.h> int usefoo(void) { return foo; } The key advantages of this sort of setup are a cleaner separation between declarations (which you need to /use/ things) and the definitions (which should normally only exist once in the program - certainly for C). The declarations and definitions only exist in one place, and they are checked for consistency - there are no "extern" declarations lying around in C files that might get out of step from changes in the headers or other files with definitions. To be consistent with this, and to work consistently with C and C++, I have a strict policy that a C (or C++) file never contains declarations without definitions (and initialisations as needed), with each definition either also declared as "extern" in a matching header file, or it is declared as "static". This sort of arrangement is very common - though many people are lazy about using "static". (In C++, you can also use anonymous namespaces, but "static" works for consistency between C and C++.) Still, gcc should have a flag to disable this warning if you have reason to use "extern const int foo = 123;" - it is, after all, correctly defined C code. > $ cat 1.c > extern const int foo = 123; > $ $HOME/gcc720/bin/gcc -c -S 1.c > 1.c:1:18: warning: 'foo' initialized and declared 'extern' > extern const int foo = 123; > ^~~ > $ $HOME/gcc720/bin/gcc -c -S -xc++ -Wall -pedantic 1$ $HOME/gcc720/bin/gcc -v > Using built-in specs. > > COLLECT_GCC=/Users/jay/gcc720/bin/gcc > COLLECT_LTO_WRAPPER=/Users/jay/gcc720/libexec/gcc/x86_64-apple-darwin16.7.0/7.2.0/lto-wrapper > Target: x86_64-apple-darwin16.7.0 > Configured with: ../gcc-7.2.0/configure -prefix=/Users/jay/gcc720 > -disable-nls -disable-bootstrap > Thread model: posix > gcc version 7.2.0 (GCC) $ > > > Thank you, > - Jay > > > > >