2

IDE:codeblocks 13.12

--------------main.cpp------------------

#include<iostream>
using namespace std;
extern const int x;
int main()
{
 cout << x << endl;
}

--------------sub.cpp-------------------

extern const int x = 10;

when I try to run the code before , the compiler show the error :

E:\NewProject\Test\main.cpp|8|undefined reference to `x'|

so, who can tell me how to solve this problem? (I have tried create a head file just like:

extern const int x;

and let both cpp file include this head file. but it make no use)

and if I want create a array at main.cpp just like:

int _array[x];

what should I do?

I'm new here, and not good at English. Thanks very much!!

bolov
76.8k17 gold badges156 silver badges248 bronze badges
asked Jan 23, 2015 at 9:14
3
  • 1
    in sub.cpp make const int x = 10 (don't add extern where you actually define the variable). Commented Jan 23, 2015 at 9:18
  • Put your extern declaration into a header file and remove the extern from your sub.cpp. #RTFM Commented Jan 23, 2015 at 9:18
  • 1
    btw I want to congratulate you and thank you for taking the time and putting the effort to properly ask your first question. It is so rare that a first question looks this ok. Welcome to Stack Overflow! Commented Jan 23, 2015 at 9:21

3 Answers 3

4

The extern keyword is saying: This is a declaration only.

For a variable, you need exactly one definition, ie. a declaration without extern somewhere else:

// foo.h
extern int i;
// foo.cc
#include "foo.h"
int i; // definition
// bar.cc
#include "foo.h"
int main () {
 ++i; // modifies global variable
}

Special Rules for const

A common use case for const variables is that you define constants in a header file and then use them everywhere else in your program:

// my_constants.h
const int NumHoursInDay = 24;
const int NumMinutesInHour = 60;

If these variables were not const, then including my_constants.h into different translation units (source files + their headers) would result in a linker error due to having multiple definitions of the variables.

The standard committee decided that this was going to be a common enough use case that they actually put a special rule for variables declared const, C++ '03 7.1.5/2:

An object declared in namespace scope with a const-qualified type has internal linkage unless it is explicitly declared extern or unless it was previously declared to have external linkage.

This means that each translation unit will have it's own private copy of the const variable. The linker won't try to merge them together and so there won't be an error.

So the first point is that you can actually just remove extern from your exmaples and your code will compile and link correctly, all because of this special behavior of const.

However, for whatever reason, if you decided you do want to declare your variable first and then have a single definition in the project, you may already have noticed that the following will still generate a linker error:

// foo.h
extern const int i;
// foo.cc
const int i = 0;

This is because the linker expects to find a definition for the i in foo.h and as the i in foo.cc has internal linkage (ie. it is invisible outside of that translation unit) the linker won't consider these objects to be the same.

This can be addressed by looking at the end of the quote from the standard:

or unless it was previously declared to have external linkage.

What we need to do is to tell the compiler that i in foo.cc should have external linkage by first declaring it with extern and then defining it without extern.

// foo.cc
extern const int i;
const int i = 0;

And the best way to do this is to include our header file so that we only have the one declaration:

// foo.cc
#include "foo.h" // contains the extern declaration of 'i'
const int i = 0;

Array Dimension

One final point is that an array dimension needs to be a constant expression. Adding to the confusion here, an extern const variable that is not defined in the current translation unit is not considered to be a constant expression:

extern const int ArrayDim;
int array[ArrayDim]; // Illegal C++

The code may compile, especially if you're using g++, as there is a C language feature called Variable Length Arrays. Behind the scenes the compiler is hiding memory allocations to support this.

As you intend to use your constant across multiple translation units and you need it to be used as a constant expression then the best option is to define your constant in a header file:

// my_constants.h
const int x = 10;
#include<iostream>
#include "my_constants.h"
using namespace std;
int main()
{
 int _array[x];
 cout << x << endl;
}
answered Jan 23, 2015 at 9:18
Sign up to request clarification or add additional context in comments.

Comments

3

extern means that your variable is just declared here but defined in another translation unit. So you can have many declaration of your constant extern const int x; but you must have exactly one definition of this constant const int x = 10;

answered Jan 23, 2015 at 9:19

Comments

0

In sub.cpp, just use

const int x = 10;
answered Jan 23, 2015 at 9:18

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.