5

考虑这些例子:

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您可以看到第一个示例也可以在那里工作,但第二个没有。但是,我看不出是什么让它们如此不同。

4

2 回答 2

6

您的第一个问题的答案可在 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在同一范围内具有不同链接的两个声明会给出未定义的行为。
于 2011-08-30T06:02:31.050 回答
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);
于 2019-06-27T11:00:04.510 回答