Considérons le code:
int main(void) { int a; }
Pour autant que je sache, int a;
est une définition, car elle entraîne la réservation du stockage. Citant la norme C (ébauche du comité N1570 – 12 avril 2011):
6.7 / 5 Sémantique Une déclaration spécifie l’interprétation et les atsortingbuts d’un ensemble d’identifiants. Une définition d’un identifiant est une déclaration pour cet identifiant qui:
– pour un object, le stockage est réservé à cet object;
…
Voici la question: le compilateur peut optimiser le stockage, car nous n’utilisons pas la variable. Est alors int a;
une déclaration alors? Et que se passe-t-il si nous faisons un printf("%p", &a)
dans main(void)
– le compilateur doit maintenant allouer le stockage, le concept de déclaration / définition dépend donc de l’utilisation ultérieure ou non de l’identifiant?
Le texte que vous avez cité dans 6.7 / 5 est en réalité censé être interprété dans le sens contraire de ce que vous avez fait: le texte dit que les définitions entraînent une allocation de stockage.
Le texte qui spécifie que int a;
est une définition est ailleurs.
C est défini en termes de machine abstraite. Il y a du stockage alloué dans la machine abstraite. Que de la mémoire soit allouée ou non sur votre PC est sans rapport.
Est alors
int a;
une déclaration alors?
Oui.
En fait, chaque définition est aussi une déclaration . Une variable ne peut avoir qu’une seule définition, mais peut avoir plusieurs déclarations.
int a;
Ceci est une définition Il y a une mémoire allouée pour la variable a
extern int a;
Ceci est une déclaration. La mémoire n’est pas allouée car elle n’est pas définie.
Une fois qu’une variable est définie, vous pouvez utiliser l’adresse de celle-ci qui est totalement légale.
Une déclaration introduit un identifiant et décrit son type, qu’il s’agisse d’un type, d’un object ou d’une fonction. Une déclaration est ce dont le compilateur a besoin pour accepter les références à cet identifiant. Ce sont des déclarations:
extern int bar; extern int g(int, int);
Une définition instancie / implémente effectivement cet identifiant. C’est ce dont l’éditeur de liens a besoin pour lier des références à ces entités. Ce sont des définitions correspondant aux déclarations ci-dessus:
int bar; int g(int lhs, int rhs) {return lhs*rhs;}