Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1050143
  • 博文数量: 288
  • 博客积分: 10306
  • 博客等级: 上将
  • 技术积分: 3182
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-12 17:00
文章分类

全部博文(288)

文章存档

2011年(19)

2010年(38)

2009年(135)

2008年(96)

我的朋友

分类: C/C++

2008-08-20 14:05:05

Declaration vs. Definition (C/C++)

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.

// definition
int i = 0;

All extern expressions (except for the one discussed above) are declarations.

// 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; // initialization for definition
extern int i; // "extern" for declaration

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)
创建于: 2007-02-12 21:27:11,修改于: 2007-06-20 22:45:23,已浏览562次,有评论3条

网友评论
网友:andreww 时间:2007-03-26 13:19:06 IP地址:192.11.236.★
有用啊 

网友:whyglinux 时间:2007-06-22 11:00:08 IP地址:122.209.141.★
int i;
extern int i = 0;

Those above are not expressions, they are declarations. Furthermore, there is no expression in the first one and in the second only the initializer 0 is an expression.

An expression followed by a semicolon forms an expression statement. Note though that in C declarations are not statements but in C++ declarations belong to declaration statements.

Most of the "expression" in your article should be "decalarion".

>> As for the second one, it is illegal in C.

You mean extern int i = 0; is invalid? In fact, it is valid by C99.

>> multiple-definition is just illegal.

Well, inline functions can and must be defined in each translation unit in which they are used. If a file scope object is defined multiple times, it is not a constraint violation or syntax error (thus not "illegal"), but undefined.

>> All initializations (i.e. expressions like following one) are definitions.

This is perhaps better: All declarations with an initializer (i.e. declarations like the following one) are definitions. 

网友:lgfang 时间:2007-06-22 21:49:35 IP地址:218.56.79.★
>> Most of the "expression" in your article should be "decalarion".

Thank you. So I was definitely wrong to use "expression".

Shall I use "statement" instead of "expression", though may not precise?
I don't want to use "declaration" since in this article "declaration"
refers to "referencing declaration" (and "definition" refers "defining
declaration").

>> You mean extern int i = 0; is invalid? In fact, it is valid by C99.

Maybe you are right. I had check the standard. The book said so, and it
claimed to covered C99. So I take it for true. Just for your
information: my test on FreeBSD suggests that GCC don't allow that
statement.

[lgfang@fbbox ~/tmp]$ cat test.c
int main(){
   extern int i =0;
    return 0;
}
[lgfang@fbbox ~/tmp]$ gcc test.c
test.c: In function `main':
test.c:2: error: `i' has both `extern' and initializer
[lgfang@fbbox ~/tmp]$ gcc -v
Using built-in specs.
Configured with: FreeBSD/i386 system compiler
Thread model: posix
gcc version 3.4.6 [FreeBSD] 20060305
[lgfang@fbbox ~/tmp]$ uname -a
FreeBSD fbbox 6.2-RELEASE FreeBSD 6.2-RELEASE #0: Fri Jan 12 10:40:27 UTC 2007     root@dessler.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  \
i386
[lgfang@fbbox ~/tmp]$

>>Well, inline functions can and must be defined in each translation
  unit in which they are used. If a file scope object is defined
  multiple times, it is not a constraint violation or syntax error (thus
  not "illegal"), but undefined.

By "multiple-definition" I mean "defining declaration" for variables.
阅读(1118) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~