请考虑以下示例:
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你可以看到第一个例子也在那里工作但第二个例子没有。但是,我看不出是什么让他们如此不同。
答案 0 :(得分:3)
您的第一个问题的答案可在C标准的第6.2.2节中找到:
4对于使用存储类说明符
extern
声明的标识符 在可以看到该标识符的先前声明的范围内, 如果事先声明指定内部或外部联系,则 后面声明中标识符的链接与 在先前声明中指定的联系。如果没有事先声明 可见,或者如果先前的声明指定没有链接,那么 标识符有外部链接。
因此a
的链接是内部的。
关于你的第二个问题,紧接在后一段的第二句是适当的:
5如果函数的标识符声明没有 存储类说明符,其链接确定就像它一样 使用存储类说明符
extern
声明。如果 对象标识符的声明具有文件范围而没有 存储类说明符,其链接是外部的。
因为a
是一个对象而不是一个函数,所以没有存储类说明符的声明int a;
会给出a
外部链接。然后同一部分说:
7如果在翻译单元中,同时出现两个标识符 内部和外部联系,行为未定义。
因为,在您的第二个示例中,a
同时显示内部和外部链接,因此会触发此段落。未定义行为的一个(特别有用)表现形式是编译器产生的错误。
这些规则可以理解您的所有示例:
int a;
始终使用外部链接声明a
; static int a;
始终声明a
内部链接; extern int a;
声明a
与已有的任何关联,或外部链接(如果没有); 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);