Why Does "Extern Const Int N;" Not Work as Expected

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 in
a.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



Leave a reply



Submit