首页 > 代码库 > C中变量重复声明

C中变量重复声明

机缘巧合在网上看到在C中用extern声明函数和不用extern声明函数是没有区别的,但却没人提用变量用extern声明有没有区别,自己稍微研究一下,发现它们还是有区别的。

刚开始找到了The GNU C Reference Manual中一段相关的描述:

Uninitialized variables that are declared as extern are given default values of 0, 0.0, or
NULL, depending on the type. Uninitialized variables that are declared as auto or register
(including the default usage of auto) are left uninitialized, and hence should not be assumed
to hold any particular value.
extern is useful for declaring variables that you want to be visible to all source files
that are linked into your project. You cannot initialize a variable in an extern declaration,
as no space is actually allocated during the declaration. You must make both an extern
declaration (typically in a header file that is included by the other source files which need to
access the variable) and a non-extern declaration which is where space is actually allocated
to store the variable. The extern declaration may be repeated multiple times.

但再阅读更多的资料后发现其中有些不对的地方。。。也是醉了。

首先上面2段中说extern变量是不会被分配空间的,但又说未初始化的extern变量会被分配默认值,自相矛盾。然后在gcc实现中,extern变量是可以被初始化的,只不过gcc会报warning:

init_test.c:3:12: warning: ‘a’ initialized and declared ‘extern’
 extern int a = 10;


根据上面2段的描述中我们可以看到extern变量是可以被多次声明的,那么非extern变量(不包括auto,register这样的)呢,文中没说是不是就以为着不能重复声明呢?自己实验一下发现编译一个重复声明变量的文件是可以通过的。

1 int a;2 int a;

一个就包含上述2行的文件是可以编译的,原因在C标准中定义了,以下摘自C99:

A declaration of an identifier for an object that has file scope without an initializer, and
without a storage-class specifier or with the storage-class specifier static, constitutes a
tentative definition. If a translation unit contains one or more tentative definitions for an
identifier, and the translation unit contains no external definition for that identifier, then
the behavior is exactly as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation unit, with an initializer
equal to 0.

所以假如在像下面这样写,是不能通过编译的:

1 int2 main (void)3 {4     int a;5     int a;6 }

init_test.c: In function ‘main’:
init_test.c:6:6: error: redeclaration of ‘a’ with no linkage
  int a;
      ^
init_test.c:5:6: note: previous declaration of ‘a’ was here
  int a;
      ^

C中变量重复声明