在 C11 中链接翻译单元的规则是什么?
What are the rules for linking translation units in C11?
C11 标准讨论了标识符的 link 时代,但没有明显讨论 linking 翻译单元的规则。我的问题是通过使用 clang 编译两个简单示例提出的。
这是我的第一个示例,它有两个相同函数但类型不兼容的声明:
//testall.c
extern char myfun(void*);
int main(){
char a='c';
a=myfun(&a);
}
char myfun(char*c){
return *c;
}
然后我运行 命令:$clang -std=c11 testall.c
然后clang报错:
testall.c:9:10: error: conflicting types for 'myfun'
char myfun(char*c){
</code> <code>
^
testall.c:2:17: note: previous declaration is here
extern char myfun(void*);
</code> <code>
</code> <code>
</code> <code>
</code> <code>
^
1 error generated.
我理解这个错误,因为 void 指针和指向 char 的指针是不兼容的类型。
令我困惑的是,当我将两个声明分成两个不同的翻译单元,然后 link 将它们合二为一时,clang 没有报告任何错误:
//test.c
extern char myfun(void*);
int main(){
char a='c';
a=myfun(&a);
}
// mylib.c
char myfun(char*c){
return *c;
}
然后我运行这个命令:$clang -std=c11 test.c mylib.c.
clang 编译并 links 这两个翻译单元,而不会报告任何错误或警告。
我在想 linking 两个翻译单元遵循 C11 标准第 6.2.2 节标识符链接中的规则。但似乎并非如此。谁能帮我澄清一下?
这只是未定义的行为。 C11 没有说明 linkers 或它们如何组合多个翻译单元。实际上,这不是问题,因为会有一个包含 myfun()
函数声明的头文件,其中包含这两个 C 文件。
在包含两个单独文件的示例中,行为未定义。这是我的“案例”,基于 C11 标准:
C11 6.2.2(4):
For an identifier declared with the storage-class specifier extern ...
If no prior declaration is visible, or if the prior
declaration specifies no linkage, then the identifier has external
linkage.
在test.c
中,myfun
有外部链接,因为它是用extern
声明的,没有可见的先前声明。
C11 6.2.2(5):
If the declaration of an identifier for a function has no storage-class
specifier, its linkage is determined exactly as if it were declared with
the storage-class specifier extern.
在mylib.c
中,myfun
声明时没有storage-class说明符,因此就好像它是用extern
声明的一样,因此它在此具有外部链接还有翻译单元。
C11 6.9.1.(7) [函数定义]:
If the declarator includes a parameter type list, the list also
specifies the types of all the parameters; such a declarator also
serves as a function prototype for later calls to the same function
in the same translation unit
因此 mylib.c
中 myfun
的定义也是 myfun
的声明(如果您有任何疑问)。
C11 6.2.2(2):
In the set of translation units and libraries that constitutes an
entire program, each declaration of a particular identifier with
external linkage denotes the same object or function.
因此两个 myfun
表示相同的功能。
C11 6.2.7(2):
All declarations that refer to the same object or function shall
have compatible type; otherwise, the behavior is undefined.
myfun
的两个声明具有不兼容的类型(我可以显示
如果你愿意的话,但这就是 Clang 在 single-file 中抱怨的原因
case.) 因此整个程序的行为是未定义的。
请注意 6.2.7(2) 不是 约束,因此 Clang 不是
需要在违反时发出诊断。然而,
在单个文件的情况下,存在实际的约束违规,
因为标题 "Constraints" 下出现以下内容:
C11 6.7(4):
All declarations in the same scope that refer to the same object
or function shall specify compatible types.
所以 Clang 必须在这种情况下发出诊断。
C11 标准讨论了标识符的 link 时代,但没有明显讨论 linking 翻译单元的规则。我的问题是通过使用 clang 编译两个简单示例提出的。
这是我的第一个示例,它有两个相同函数但类型不兼容的声明:
//testall.c
extern char myfun(void*);
int main(){
char a='c';
a=myfun(&a);
}
char myfun(char*c){
return *c;
}
然后我运行 命令:$clang -std=c11 testall.c
然后clang报错:
testall.c:9:10: error: conflicting types for 'myfun'
char myfun(char*c){
</code> <code>
^
testall.c:2:17: note: previous declaration is here
extern char myfun(void*);
</code> <code>
</code> <code>
</code> <code>
</code> <code>
^
1 error generated.
我理解这个错误,因为 void 指针和指向 char 的指针是不兼容的类型。
令我困惑的是,当我将两个声明分成两个不同的翻译单元,然后 link 将它们合二为一时,clang 没有报告任何错误:
//test.c
extern char myfun(void*);
int main(){
char a='c';
a=myfun(&a);
}
// mylib.c
char myfun(char*c){
return *c;
}
然后我运行这个命令:$clang -std=c11 test.c mylib.c.
clang 编译并 links 这两个翻译单元,而不会报告任何错误或警告。
我在想 linking 两个翻译单元遵循 C11 标准第 6.2.2 节标识符链接中的规则。但似乎并非如此。谁能帮我澄清一下?
这只是未定义的行为。 C11 没有说明 linkers 或它们如何组合多个翻译单元。实际上,这不是问题,因为会有一个包含 myfun()
函数声明的头文件,其中包含这两个 C 文件。
在包含两个单独文件的示例中,行为未定义。这是我的“案例”,基于 C11 标准:
C11 6.2.2(4):
For an identifier declared with the storage-class specifier extern ... If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.
在test.c
中,myfun
有外部链接,因为它是用extern
声明的,没有可见的先前声明。
C11 6.2.2(5):
If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern.
在mylib.c
中,myfun
声明时没有storage-class说明符,因此就好像它是用extern
声明的一样,因此它在此具有外部链接还有翻译单元。
C11 6.9.1.(7) [函数定义]:
If the declarator includes a parameter type list, the list also specifies the types of all the parameters; such a declarator also serves as a function prototype for later calls to the same function in the same translation unit
因此 mylib.c
中 myfun
的定义也是 myfun
的声明(如果您有任何疑问)。
C11 6.2.2(2):
In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function.
因此两个 myfun
表示相同的功能。
C11 6.2.7(2):
All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.
myfun
的两个声明具有不兼容的类型(我可以显示
如果你愿意的话,但这就是 Clang 在 single-file 中抱怨的原因
case.) 因此整个程序的行为是未定义的。
请注意 6.2.7(2) 不是 约束,因此 Clang 不是 需要在违反时发出诊断。然而, 在单个文件的情况下,存在实际的约束违规, 因为标题 "Constraints" 下出现以下内容:
C11 6.7(4):
All declarations in the same scope that refer to the same object or function shall specify compatible types.
所以 Clang 必须在这种情况下发出诊断。