静态声明后的非静态声明

时间:2011-08-30 05:07:35

标签: c storage duration linkage

请考虑以下示例:

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

为什么在第一个例子中没有问题,但在第二个例子中没有?

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

谢谢

AFAIK,功能的链接和存储持续时间略有不同。

编辑: 我尝试使用gcc 4.5.2 -Wall -pedantic --std = c99

进行编译

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

2 个答案:

答案 0 :(得分: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的两个声明会给出未定义的行为。

答案 1 :(得分:0)

当我忘记“ {”而不是“;”时,我遇到了同样的错误。在声明的末尾。

示例:

extern void *HASHMP_get(struct HASHMP_wf_s *hmwf_ptr, Uint8 *key);
extern void *HASHMP_remove(struct HASHMP_wf_s *hmwf_ptr, Uint8 *key) {
extern Uint16 HASHMP_clear(struct HASHMP_wf_s *hmwf_ptr);