Les normes C11 parlent du couplage des identificateurs, mais il n'y a pas de discussion évidente sur les règles de liaison des unités de traduction. Ma question est soulevée en compilant deux exemples simples en utilisant clang.Quelles sont les règles pour lier les unités de traduction en C11?
Voici mon premier exemple, qui a deux déclarations de la même fonction, mais avec des types incompatibles:
//testall.c
extern char myfun(void*);
int main(){
char a='c';
a=myfun(&a);
}
char myfun(char*c){
return *c;
}
Puis-je exécuter la commande suivante: $ clang std = c11 testall.c
et les rapports de Clang une erreur:
testall.c:9:10: error: conflicting types for 'myfun'
char myfun(char*c){
^
testall.c:2:17: note: previous declaration is here
extern char myfun(void*);
^
1 error generated.
Je comprends cette erreur, car le pointeur vide et le pointeur sur char sont des types incompatibles.
Ce qui me confond est que lorsque je sépare les deux déclarations en deux unités de traduction différentes, puis de les relier en un seul, clang ne signale aucune erreur:
//test.c
extern char myfun(void*);
int main(){
char a='c';
a=myfun(&a);
}
// mylib.c
char myfun(char*c){
return *c;
}
J'exécuter cette commande: $ clang std = c11 test.c mylib.c. Clang compile et relie les deux unités de traduction sans signaler d'erreur ou d'avertissement. Je pensais que lier deux unités de traduction suit les règles de la section 6.2.2 Liaisons d'identifiants des normes C11. Mais il semble que ce ne soit pas le cas. Quelqu'un peut-il m'aider à le clarifier?
Ce n'est pas parce que vous ne recevez pas de diagnostic que le code est légal! Traditionnellement, un compilateur ne regarde qu'une seule unité de traduction à la fois (il ne peut donc pas détecter la discordance lors de la compilation) et les informations de type ne sont pas transmises au fichier objet, de sorte que l'éditeur de liens ne peut pas détecter la discordance non plus. –
@NateEldredge Essayez de faire un fichier à la fois au lieu de spécifier les deux sur la ligne de commande. Faire 'gcc a.c b.c' compile et lie en une seule étape. C ne fait pas de nom mangling donc les noms de la fonction ressemblent exactement à l'éditeur de liens. Maintenant, que se passe-t-il si vous avez trois fichiers objets avec 'myfun'? Vous obtiendrez une erreur de redéfinition de la fonction. Donc, clairement, ce que vous avez dit ne peut pas être vrai. –
Bien que 'gcc a.c b.c' exécute à la fois le compilateur et l'éditeur de liens, il s'agit de deux passages distincts qui ne partagent pas d'informations autres que le fichier objet. L'éditeur de liens est capable de détecter plusieurs ** définitions ** du même symbole. Mais dans votre exemple, la fonction 'myfun' est seulement ** définie ** une fois, dans' mylib.c'. Le fichier 'test.c' contient une ** déclaration ** de' myfun' mais pas de ** définition **. Par conséquent, aucune erreur de l'éditeur de liens. –