source - static code analysis tools




Définitions provisoires en C99 et liens (2)

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 la norme C99 est que ce programme devrait être rejeté. Dans mon interprétation du 6.9.2, la variable x 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, devrait donc se comporter comme si f1.c contenait la définition int x=0; .

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

Je doute que cela se produise par accident, ou simplement comme une fonctionnalité "facile" à fournir en plus de ce que la norme exige. Si vous y réfléchissez, cela signifie qu'il existe un support spécial dans l'éditeur de liens pour les variables globales qui ne possèdent pas d'initialiseur, par opposition à celles explicitement initialisées à zéro. Quelqu'un m'a dit que la fonctionnalité de l'éditeur de liens pourrait être nécessaire pour compiler Fortran de toute façon. Ce serait une explication raisonnable.

Des pensées à ce sujet? Autres interprétations de la norme? Noms des plates-formes sur lesquelles les fichiers f1.c et f2.c refusent d'être liés entre eux?

Remarque: ceci est important car la question se pose dans le contexte de l'analyse statique. Si les deux fichiers peuvent ne pas être liés sur une plate-forme, l'analyseur doit se plaindre, mais si chaque plate-forme de compilation l'accepte, il n'y a aucune raison d'en avertir.


Ceci est pour clarifier ma réponse à un commentaire de Olovb:

sortie de nm pour un fichier objet compilé à partir de "int x;". Sur cette plate-forme, les symboles sont précédés d'un «_», c'est-à-dire que la variable x apparaît sous la forme _x.

00000000 T _main
         U _unknown
00000004 C _x
         U dyld_stub_binding_helper

sortie de 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 de 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 de nm pour un fichier objet compilé à partir de "extern int x;"

00000000 T _main
         U _unknown
         U dyld_stub_binding_helper

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

00000000 T _main
         U _unknown
         U _x
         U dyld_stub_binding_helper

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

La page liée indique que ceci est pertinent pour les plates-formes Unix - je suppose que c'est la même chose pour c99 que pour c89 - bien que d'autres compilateurs aient adopté cette norme pour former une sorte de norme de facto. Intéressant.





c99