Why does extern const int n; not work as expected?
It's because const
implies internal linkage by default, so
your "definition" isn't visible outside of the translation unit
where it appears.
In this case, by far the best solution is to put the declaration
(extern int const n;
) in a header file, and include that in
both a.cpp
and b.cpp
. The linkage is determined by the
first declaration the compiler sees, so the later definition ina.cpp
will have the correct (external) linkage.
Alternatively, you can force the linkage in the definition:
extern int const n = 8;
Despite the extern
, this is still a definition; anything with
an initializer outside of a class definition is a definition.
C++ Referencing extern const within a namespace
If you define SIZE
without the extern
keyword, it will have internal linkage since it is const
. You can refer to it inmain.cpp
as TAXCONSTANTS::SIZE
. This is recommended since the compiler will be able to inline the value wherever SIZE
is used.
If you define SIZE
with the extern
keyword, it will have external linkage and it should not be in a header, unless you want multiple definition errors. You should instead define it in a .cpp
file which will be linked into the rest of the program. In this case there will be only one copy of SIZE
in the entire program. You should avoid this approach (preferring instead the approach without extern
) unless for some reason you actually need to have only one copy of SIZE
in the entire program.
In both cases, SIZE
will be a member of the TAXCONSTANTS
namespace.
Your attempt to redeclare SIZE
inside main
does not do what you think it does! The following inside main
:
extern const int SIZE;
actually has the effect of declaring SIZE
in the global namespace. Since there is no definition of SIZE
in the global namespace, you get undefined reference errors at link time. It is not the correct way to refer to the SIZE
variable defined in TAXCONSTANTS
.
Why does const extern give an error?
Standard says:
C11-§6.7/4
All declarations in the same scope that refer to the same object or function shall specify compatible types
const int
and int
are not compatible for the same object foo
in the same scope.
C++ extern const char* not working as expected
The lifetime of somePath.c_str()
is bound by the somePath
variable. As soon as it goes out of scope, PATH
points to memory that will be re-used.
Can you make PATH
a std::string
instead of a char*
? If not, you will have to duplicate the value of somePath.c_str()
using strdup
or something similar.
Is it valid to treat an extern global as const when the definition is not const?
It's clearly undefined as the declarations don't match. As you noted, const int
and int
aren't compatible types. A diagnostic is required only if they appear in the same scope.
It isn't safe in practice either, consider
$ cat test1.c
#include <stdio.h>
extern const int n;
void foo(void);
int main(void) {
printf("%d\n", n);
foo();
printf("%d\n", n);
}
$ cat test2.c
int n;
void foo(void) { ++n; }
$ gcc -std=c99 -pedantic test1.c test2.c && ./a.out
0
1
$ gcc -O1 -std=c99 -pedantic test1.c test2.c && ./a.out
0
0
Gcc assumes that n
isn't changed by foo()
when optimizing, because it may assume the definition of n
is of a compatible type, thus const
.
Chances are that you get the expected behaviour with also volatile
-qualifying n
in test1.c
, but as far as the C standard is concerned, this is still undefined.
The best way I can think of to prevent the user from accidentally modifying n
is to declare a pointer to const
, something along
int my_real_variable;
const int *const my_variable = &my_real_variable;
or perhaps some macro
#define my_variable (*(const int *)&my_variable)
With C99, my_real_variable
can be avoided via a compound literal:
const int *const my_variable_ptr = &(int){ 12 };
It would be legal to cast away const
here (as the int
object itself isn't const
), but the cast would be required, preventing accidental modification.
Why const objects are local to file in c++?
In C++, when you declare a variable to be const
at namespace scope it automatically has internal linkage. Adding static
will also yield in internal linkage with or without const
Therefore they are not available outside the translation unit, hence the linker error.
Related Topics
What's the Behavior of an Uninitialized Variable Used as Its Own Initializer
Check at Compile-Time If Template Argument Is Void
How Does Modulus and Rand() Work
Error Lnk1104: Cannot Open File 'Debug\Myprojectlib.Lib'
How to Get the Size of a Memory Block Allocated Using Malloc()
How to Create Nvidia Opencl Project
Comparison of Double, Long Double, Float and Float128
Why Is the Sprite Not Rendering in Opengl
How Does Std::Move() Transfer Values into Rvalues
Linking Libstdc++ Statically: Any Gotchas
How to Make Generic Computations Over Heterogeneous Argument Packs of a Variadic Template Function
"No Newline at End of File" Compiler Warning
Differencebetween Const_Iterator and Non-Const Iterator in the C++ Stl
Temporary Objects - When Are They Created, How to Recognise Them in Code