TITLE: constant declarations in include files (Newsgroups: comp.lang.c++.moderated, 6 Sep 99) [ This is a snippet of a discussion on declarations and definitions of constants in include files. -adc ] JKB: > But there's another answer, or else it's a question. Is it the > compiler or the linker that complains? If it's the compiler, > then you have the include-guard situation. Or the linker might > complain, since your definition of PI is in multiple translation > units. What you may need is a declaration in the header, with a > definition in only one place: > > extern const float PI; // this is in constants.h > const float PI=3.14; // this is in constants.cpp > > Here's the reason why I'm not sure about whether the > definition-declaration thing is an issue or not. My linker accepts > your code if PI is declared as 'const', but reports a > multiple-definition error if it's not const. So a question - is > this behavior per spec, or is MSVC just being weird? NARAN: Siemel B. Naran Your compiler MSVC is right. Constant variables have internal linkage by default, so each file that includes constants.hh gets its own copy of the constant variables. Thus you get no multiple definition errors at link time. This would be inefficient were it not for one optimization: the compiler may substitute the value of the const value wherever it is used, and may eliminate storage of the variable. The compiler egcs does this optimization. If I'm not mistaken, most compilers do this optimization. (If you use the address of the variable, or if you compile with debugging or without optimization, then the compiler does not do the optimization.) Aside: all of the following are constant variables: const double pi=3.14; char const *const text="hello world"; char *const text="hello world"; const char text[]="hello world"; The other way to define const variables uses extern and gaurantees that there is one copy of the variables in the entire system. This is what you observed above. // constants.h namespace mathlib { extern const double pi; } // constants.c #include "constants.h" const double mathlib::pi=3.14; One disadvantage of this method is that the compiler may not substitute the value of the variable wherever it is used. More concretely, suppose we had // A.hh #include "constants.h" inline double A() { return mathlib::pi; } then the file A.o will not have the constant 3.14 hard-coded into it. Instead, there will be code to look up the value of mathlib::pi at runtime. Of course, the linker may do the same optimization at link time: that is, replace the code to lookup mathlib::pi with the actual value of mathlib::pi. But this means rewriting the code of A.o at link time, and I'm not sure how many compiler/linkers are up to the task. Besides, if the file constants.o is part of a dynamic library, then the optimization is not possible anyway.