2011-08-30 95 views
4

非静态声明考虑这些例子:下面的静态声明

static int a; 
extern int a; //OK -- what linkage does the a have now? 

static int a; 
int a; //ERROR 

extern int a; 
static int a; //ERROR 

int a; 
static int a; //ERROR 

extern int a; 
int a; //OK as expected 

int a; 
extern int a; //OK as expected 

为什么它是在第一个例子确定,但不是在第二?

就文件范围变量(全局范围)而言,当没有指定关键字时,它们具有外部链接和静态持续时间。

谢谢

据我所知,连接和存储持续时间功能是一个有点不同。

编辑: 我尝试用gcc 4.5.2编译-Wall -pedantic --std = C99

更多:http://c-faq.com/decl/static.jd.html你可以看到,第一个例子在那里工作过,但第二次却没有。但是,我不明白是什么让他们如此不同。

+0

你可以更多地回答你的问题吗?因为在你第一次关心你评论确定,但是会产生一个错误,说“静态声明'a'遵循非静态声明” – 2011-08-30 05:56:34

回答

3

答案第一个问题在C标准的§6.2.2中找到:

4为了与存储类说明extern 在范围中声明的标识符,其中的先前声明如果先前的声明指定了内部或外部链接,则后面声明中标识符的 链接与先前声明中指定的链接 相同。如果前面的声明不可见,或者前面的声明没有指定链接,则 标识符具有外部链接。

所以a的链接是内部的。

关于第二个问题,紧随其后段落的第二句是中肯的:

5如果一个标识符的某个函数的声明没有 存储类说明,其联动是完全一样的决定如果它使用存储类说明符extern声明了 。如果一个对象的标识符的 声明具有文件范围,并且没有 存储类说明符,则其链接是外部的。

因为a是一个对象,而非函数,声明int a;没有存储类说明给出a外部连接。相同的部分于是具有这样说的:

7如果,一个翻译单元内,相同的标识符出现既 内外联动,该行为是未定义。

由于在第二个示例中,a与内部和外部链接一起显示,因此会触发此段落。一个(特别有用的)未定义行为的表现是编译器正在产生的错误。

您所有的例子可以通过这些规则来理解:

  1. int a;总是宣称a外部链接;
  2. static int a;总是声明a与内部联系;
  3. extern int a;声明a与它已有的任何链接,或者如果它没有外部链接;
  4. a在相同范围内的两个声明有不同的联系,给出未定义的行为。
+0

我想知道,外部继承链接的基本原理是什么?至于我,这只会造成混乱。 – mindless

+0

“如果事先声明指定内部或外部链接”。 这是否意味着它应该被明确指定,或者它也可以被隐决定就像是在你的第二个段落中提到: “如果一个函数的标识符的声明没有存储类说明,其联动是完全一样的决定如果它是用存储类说明符extern声明的“。 – mindless

+0

@mindless:我不认为这很重要 - 那是'int a; extern int a;'case。 'extern int a''声明有外部链接,因为'int a;'声明有外部链接,或者它有外部链接,因为'int a;'声明(直接)没有指定链接 - 无论你使用什么样的解释, 结果是一样的。顺便说一句,你引用第5段的第一句话是关于功能的。 – caf