Question

Considérons le programme C composé de deux fichiers,

f1.c:

int x;

f2.c:

int x=2;

Ma lecture du paragraphe 6.9.2 de C99 norme est que ce programme devrait être rejeté. Dans mon interprétation de 6.9.2, x variable est provisoirement définie dans f1.c, mais cette définition provisoire devient une définition réelle à la fin de l'unité de traduction, et (à mon avis), doit se comporter donc comme si f1.c contenait la int x=0; définition.

Avec tous les compilateurs (et, surtout, linkers) j'ai pu essayer, ce n'est pas ce qui se passe. Toutes les plates-formes de compilation j'ai essayé do relier les deux fichiers ci-dessus, et la valeur de x est 2 dans les deux fichiers.

Je doute que cela arrive par accident, ou tout simplement comme un élément « facile » pour fournir, en plus de ce que la norme exige. Si vous y pensez, cela signifie qu'il ya un soutien particulier dans l'éditeur de liens pour les variables globales qui ne sont pas un initialiseur, par opposition à ceux explicitement initialisé à zéro. Quelqu'un m'a dit que la fonction de liaison peut être nécessaire de compiler Fortran de toute façon. Ce serait une explication raisonnable.

Les réflexions à ce sujet? D'autres interprétations de la norme? Les noms des plates-formes sur lesquelles les fichiers f1.c et f2.c refusent d'être reliés entre eux?

Note: Ceci est important car la question se produit dans le contexte de l'analyse statique. Si les deux fichiers peuvent refuser d'être lié sur une plate-forme, l'analyseur doit se plaindre, mais si chaque plate-forme de compilation accepte alors il n'y a aucune raison de mettre en garde à ce sujet.

Était-ce utile?

La solution

Voir aussi Quelles sont les variables externat en C . Ceci est mentionné dans la norme C à l'annexe informative J comme extension:

  

J.5.11 définitions externes multiples

     

Il peut y avoir plus d'une définition externe pour l'identifiant d'un objet, avec ou sans l'utilisation explicite du mot-clé extern; si les définitions sont en désaccord, ou plus d'un est initialisé, le comportement est indéfini (6.9.2).

Avertissement

Comme @litb souligne ici, et comme indiqué dans ma réponse à la question des renvois, en utilisant de multiples définitions pour une variable globale conduit à un comportement non défini, ce qui est la façon la norme de dire « tout peut arriver ». L'une des choses qui puisse arriver est que le programme se comporte comme prévu; et dit J.5.11, environ, « vous pourriez avoir de la chance plus souvent que vous méritez ». Mais un programme qui repose sur plusieurs définitions d'une variable extern - avec ou sans le mot-clé explicite « extern » - est pas un programme strictement conforme et ne pas fonctionner partout. De manière équivalente. Il contient un bug qui peuvent ou peuvent ne pas se montrer

Autres conseils

Il y a quelque chose appelé une « extension commune » à la norme, où la définition des variables plusieurs fois est autorisé tant que la variable est initialisée qu'une seule fois. Voir http://c-faq.com/decl/decldef.html

La page liée dit ceci est pertinent pour les plates-formes Unix - Je suppose que c'est la même pour C99 que c89 - mais peut-être qu'il a été adopté par plus de compilateurs pour former une sorte de norme de fait. Intéressant.

est de clarifier ma réponse à un commentaire par olovb:

sortie nm pour un fichier objet compilé à partir de « int x; ». Sur cette plate-forme, les symboles sont préfixées avec « _ », à savoir, la variable x apparaît comme _x.

00000000 T _main
         U _unknown
00000004 C _x
         U dyld_stub_binding_helper

sortie nm pour un fichier objet compilé à partir de "int x = 1;"

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

sortie nm pour un fichier objet compilé à partir de "int x = 0;"

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

sortie nm pour un fichier objet compilé à partir de "extern int x;"

00000000 T _main
         U _unknown
         U dyld_stub_binding_helper

EDIT: sortie nm pour un fichier objet compilé à partir de "extern int x;" où x est en fait utilisé dans l'une des fonctions

00000000 T _main
         U _unknown
         U _x
         U dyld_stub_binding_helper
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top