Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constant definition in multiple files

Tags:

c++

constants

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";
like image 366
drdot Avatar asked Apr 04 '15 18:04

drdot


1 Answers

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.

like image 67
eerorika Avatar answered Nov 17 '22 17:11

eerorika