Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Mail Systems
Eclipse Documentation

How To Guides
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Problem Solutions
Privacy Policy




Thinking in C++
Prev Contents / Index Next

Differences with C

Constants were introduced in early versions of C++ while the Standard C specification was still being finished. Although the C committee then decided to include const in C, somehow it came to mean for them “an ordinary variable that cannot be changed.” In C, a const always occupies storage and its name is global. The C compiler cannot treat a const as a compile-time constant. In C, if you say

const int bufsize = 100;
char buf[bufsize];

you will get an error, even though it seems like a rational thing to do. Because bufsize occupies storage somewhere, the C compiler cannot know the value at compile time. You can optionally say

const int bufsize;

in C, but not in C++, and the C compiler accepts it as a declaration indicating there is storage allocated elsewhere. Because C defaults to external linkage for consts, this makes sense. C++ defaults to internal linkage for consts so if you want to accomplish the same thing in C++, you must explicitly change the linkage to external using extern:

extern const int bufsize; // Declaration only

This line also works in C.

In C++, a const doesn’t necessarily create storage. In C a const always creates storage. Whether or not storage is reserved for a const in C++ depends on how it is used. In general, if a const is used simply to replace a name with a value (just as you would use a #define), then storage doesn’t have to be created for the const. If no storage is created (this depends on the complexity of the data type and the sophistication of the compiler), the values may be folded into the code for greater efficiency after type checking, not before, as with #define. If, however, you take an address of a const (even unknowingly, by passing it to a function that takes a reference argument) or you define it as extern, then storage is created for the const.

In C++, a const that is outside all functions has file scope (i.e., it is invisible outside the file). That is, it defaults to internal linkage. This is very different from all other identifiers in C++ (and from const in C!) that default to external linkage. Thus, if you declare a const of the same name in two different files and you don’t take the address or define that name as extern, the ideal C++ compiler won’t allocate storage for the const, but simply fold it into the code. Because const has implied file scope, you can put it in C++ header files with no conflicts at link time.

Since a const in C++ defaults to internal linkage, you can’t just define a const in one file and reference it as an extern in another file. To give a const external linkage so it can be referenced from another file, you must explicitly define it as extern, like this:

extern const int x = 1;

Notice that by giving it an initializer and saying it is extern, you force storage to be created for the const (although the compiler still has the option of doing constant folding here). The initialization establishes this as a definition, not a declaration. The declaration:

extern const int x;

in C++ means that the definition exists elsewhere (again, this is not necessarily true in C). You can now see why C++ requires a const definition to have an initializer: the initializer distinguishes a declaration from a definition (in C it’s always a definition, so no initializer is necessary). With an extern const declaration, the compiler cannot do constant folding because it doesn’t know the value.

The C approach to const is not very useful, and if you want to use a named value inside a constant expression (one that must be evaluated at compile time), C almost forces you to use #define in the preprocessor.

Thinking in C++
Prev Contents / Index Next

   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire