I am reading "C++ primer plus". In Chapter 9, it talks about the difference between C++ and C when dealing with const modifier:
"In C++ (but not C), the const modifier alters the default storage classes slightly. Whereas a global variable has external linkage by default, a const global variable has internal linkage by default.
...
If global const declaration had external linkage as regular variable do, this would be an error because you can define a global variable in one file only. That is, only one file can contain the proceding declaration, and the other files have to provide reference declarations using the extern keywords."
I tried to test this claim with the following program:
file.h:
using namespace std;
const char *constant = "Magic";
file1.cpp
#include <iostream>
#include "file.h"
extern void file2();
int main(){
cout << "constant = " << constant << endl;
file2();
}
file2.cpp
#include <iostream>
#include "file.h"
void file2(){
cout << "file2 constant = " << constant << endl;
}
Makefile:
CFLAGS = -Wall -g
INCLUDE = file.h
src = file2.cpp file1.cpp
all: $(src) $(INCLUDE)
g++ $(CFLAGS) -o file $(src)
clean:
rm -f file
When I do make, i get the following error message:
g++ -Wall -g -o file file2.cpp file1.cpp
/tmp/ccdl16Tw.o:(.data+0x0): multiple definition of `constant'
/tmp/ccA3ZEHa.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
make: *** [all] Error 1
gcc version 4.8.2
UPDATE:
If I do
char* const constant = "Magic";
Then make will give me this warning:
g++ -Wall -g -o file file2.cpp file1.cpp
In file included from file2.cpp:2:0:
file.h:3:24: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
char* const constant = "Magic";
^
In file included from file1.cpp:2:0:
file.h:3:24: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
char* const constant = "Magic";
const char *constant
is not const
. It is a non-const
pointer to const char
. Being non-const
variable in namespace scope, it has external linkage by default and thus you get multiple definition error.
const char * const constant
is const
and would behave as you are expecting.
Update:
char* const constant
on the other hand would be a const
pointer to char
. Being const
it does have internal linkage by default in namespace scope.
However, you shouldn't initialize it with a string literal (as the compiler warning points out) because that's not allowed by the standard (such conversion is illegal in c++11 and was deprecated before that). String literals are allowed to be stored in read only memory and you aren't allowed to modify them runtime. That is why pointing to a string literal with a pointer to non-const char
is dangerous.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With