外部,内部和没有联系或为什么这不起作用?
根据C标准:
在构成整个程序的翻译单元和库的集合中,具有外部链接的特定标识符的每个声明表示相同的对象或function。 在一个翻译单元内,具有内部链接的标识符的每个声明表示相同的对象或function。 没有链接的标识符的每个声明表示唯一的实体。
在我的例子中,我们有三个单独的声明,每个标识符具有不同的链接。所以为什么这不起作用?
static int a; //a_Internal int main(void) { int a; //a_Local { extern int a; //a_External } return 0; }
错误:
在函数’main’中:第9行:错误:变量先前声明’static’relayclared’extern’
为什么编译器坚持要重新声明我而不是尝试访问另一个文件中的外部对象?
有效的C ++示例供参考:
static void f(); static int i = 0; // #1 void g() { extern void f(); // internal linkage int i; // #2 i has no linkage { extern void f(); // internal linkage extern int i; // #3 external linkage } }
Clang和VC似乎都适用于我的C示例; 只有某些版本的GCC(并非全部)产生上述错误。
§6.2.2,7说:
如果在翻译单元中,同一标识符同时出现内部和外部链接,则行为未定义。
所以,你的程序有不确定的行为 。
§6.2.2,4表示
extern int a; //a_External
具有外部链接,因为先前声明在范围int a; //a_Local
可见int a; //a_Local
int a; //a_Local
没有链接 。 但
static int a; //a_Internal
声明a
内部链接。 因此,根据§6.2.2,7 未定义 。
编译器给出了这个错误,因为在a_External
范围内, a_Internal
仍然可以访问,因此你在a_Internal
从static
重新声明为extern
,因为a
的名称冲突。 通过使用不同的变量名称可以解决此问题,例如:
static int a1; //a_Internal int main(void) { int a2; //a_Local { extern int a3; //a_External } return 0; }
C标准说:
在该组翻译单元中,具有外部链接的特定标识符的每个声明表示相同的实体(对象或function)。 在一个翻译单元内,具有内部链接的标识符的每个声明表示相同的实体。
在翻译单元集中,我们不能有多个具有相同名称的不同外部实体,因此表示该单个外部实体的每个声明的类型应该一致。 我们可以在一个翻译单元中检查类型是否一致,这是在编译时完成的。 我们无法在编译时或链接时检查不同翻译单元之间的类型是否一致。
对于在该标识符的先前声明可见的范围内使用存储类说明符extern声明的标识符,31)如果先前声明指定内部或外部链接,则后面声明中的标识符的链接与在先前声明中指定的联系。 如果没有先前声明可见,或者先前声明未指定链接,则标识符具有外部链接。
static int a; //a_Internal int main(void) { int a; //No linkage { extern int a; //a_External } return 0; }
这里前面的标识符声明a没有链接,所以extern int a
有外部链接。 这意味着我们必须在另一个翻译单元中定义int。 但是, GCC决定用变量先前声明的static
重新声明的’extern’错误拒绝此代码,可能是因为我们根据C
标准有未定义的行为。