Declaration vs. Definition (C/C++)
last-edit: Fang lungang 06-20-2007 22:36>
Terminologies
The terminologies "definition" and "declaration" in this article are adopted from The C++ Programming Language (Special edition) (TC++PL for short). In C: A Reference Manual (Reference for short) they are called "defining declaration" and "referencing declaration" respectively.
Introduction
Distinguishing definitions from declarations are important since header files containing definitions could cause subtle problems (refer to appendix ).
This article is based on Reference and TC++PL. It reflects the test results of gcc and g++ of version (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-20). However, according to Reference, other C compiler's behavior may differ.
Confusing Expressions
The most confusing expressions (which are also where differences between C and C++ exist) are following two kinds of expressions:
int i;
extern int i = 0;
For the first one, it is a definition in C++. In C the situation is rather complicated. The expression is deemed as a declaration if there is a definition in the same translation unit. Otherwise compiler will automatically define an i
for you. But On linkage, variables defined by that means will be dealt with specially. Reference says that different compilers may choose different rules. According to test, GCC chooses which is called Mixed Common Model (4.8.4) by Reference. That is: if there are more than one translation unit contains such definition for i
, those definitions will be combined into only one definition. Note how that is different from other kinds of definitions: multiple-definition is just illegal.
As for the second one, it is illegal in C. But in C++, the extern
is silently ignored.
For a full discussion on C/C++ compatibility for declaration (of a more general sense), please refer to section 4.9 of Reference.
More Clear Ones
In fact, there are more clear expressions. They mean the same in C/C++ as well.
All initializations (i.e. expressions like following one) are definitions.
int i = 0;
All extern
expressions (except for the one discussed above) are declarations.
extern int i;
For functions and structures, following are declarations:
struct s;
void f();
Section 9.2.3 of TC++PL detailed One Definition Rule (ODR). The ODR says that definitions of "class", "inline function", "template" can be repeated if and only if in different translation unit. Reference doesn't mention any rule alike. Nor did I find a way to test.
Advice
Avoid following expressions, especially the first one:
int i;
extern int i = 0;
Instead, using following kinds of expressions for declarations and definitions respectively whenever possible:
int i = 0; extern int i;
The reasons:
- Those two kinds of expression are more portable not only between C and C++ but also among C compilers.
- Using initialization for definition helps to develop a good habit of initialize a variable when defining it: although compiler will initialize global variables for you, that is not the case for automatic variables.
A.1 Header Files and Definitions
If a header file which contains a definition is included by more than one source files, each translation unit will get its own copy of that definition after preprocessing. The best result you may expect is that you'll get "multiple definition" error on linkage (except for ODR in C++). But there are also chances that compiler silently give you multiple instances of the variable. So it's always better to not put any definition in header files except for "const" variables and ODR (refer to Section 9.2.1 of TC++PL for more about what a header files should/shouldn't contain) .
A.2 Bibliography
- C: A Reference Manual
-
- The C++ Programming Language (Special Edition)