Types en conflit pour la variable de pointeur en C (Erreur)

(1)

#include  #include  int a = 10, b = 20 , c = 30, d, e, *pa, *pb, *pc; d= 10; e= 100; pa = &a; pb = &b; int main() { printf("%i, %i, %i, %i", pa, pb, d, e); return 0; } 

(2)

 #include  #include  int a = 10, b = 20 , c = 30, d, e, *pa, *pb, *pc; d= 10; e= 100; int main() { pa = &a; pb = &b; printf("%i, %i, %i, %i", pa, pb, d, e); return 0; } 

Pourquoi est-ce que je reçois une erreur lorsque j’initialise les variables de pointeur pa et pb en dehors de la fonction principale (1) ? Lorsque pa et pb sont dans la fonction principale, cela fonctionne parfaitement (2) . Pourquoi puis-je initialiser des variables normales en dehors de la fonction principale (d, e) mais pas des variables de pointeur?

Le message d’erreur que je reçois dans CodeBlocks est le suivant: Types de fichiers en conflit pour pa. La déclaration précédente de pa était ici: ligne 4.

Le code exécutable doit aller dans les fonctions. Cela est dû au fait que le stream d’exécution d’un programme C commence par l’appel de main() .

Des lignes comme int a = 10; sont appelées déclarations et peuvent être considérées comme “se produisant” avant le début du programme. Généralement, le compilateur génère un bloc de toutes les données des variables globales et le charge au démarrage de votre programme.

Quand vous écrivez d = 10; dans la scope du fichier, ceci est traité comme int d = 10; . Comme les instructions ne sont pas autorisées dans l’étendue du fichier, il ne s’agit pas d’une instruction d’affectation. Le compilateur pense que c’est une déclaration dans laquelle vous vouliez écrire int mais que vous vouliez sauvegarder en tapant dessus.

Ceci est appelé implicite int et C89 l’avait, bien qu’il ait été supprimé dans C99.

Alors, quand vous écrivez pa = &a; , int implicite le rend int pa = &a; et vous obtenez une erreur parce que vous avez déclaré pa avec le type int * , puis de nouveau avec int , qui sont des types différents.

Cependant, déclarer une variable en tant int et ensuite en le déclarant en tant int (comme vous l’avez fait pour d et e ) est acceptable tant que la première n’a pas d’initialiseur. C’est ce qu’on appelle une définition provisoire .

Pour éviter tout cela, assurez-vous que tout code qui n’est pas censé être une déclaration va à l’intérieur d’une fonction. Vous pouvez écrire à la scope du fichier:

 int a = 5; int *pa = &a; 

etc.


En outre, printf("%i, %i, %i, %i", pa, pb, d, e); provoque un comportement indéfini . Le spécificateur %i doit correspondre à un int . Pour résoudre ce problème, vous devez soit passer (int)pa au lieu de pa , etc., ou utiliser le spécificateur %p .

vous pouvez initialiser les pointeurs en dehors de main (), mais la déclaration doit être définie ultérieurement. Vérifiez le code:

 ` #include  #include  int a = 10, b = 20 , c = 30, d, e; d= 10; e= 100; int *pa = &a; int *pb = &b; int main() { printf("%p, %p, %i, %i", pa, pb, d, e); return 0; } 

`

L’affectation et l’initialisation sont des opérations différentes.

 int *pa = &a; 

est une déclaration avec un initialiseur et peut se produire dans une fonction ou dans l’étendue du fichier.

 int *pa; pa = &a; 

est une déclaration suivie d’une instruction d’affectation. Les instructions d’affectation (comme toute autre instruction exécutable) doivent figurer dans le corps d’une fonction.

Je vais deviner qu’il s’agit d’un compilateur plus ancien qui autorise encore les déclarations int implicites, donc il traite les déclarations

 d = 10; e = 100; 

comme définissant des déclarations avec des initialiseurs, pas comme des instructions d’affectation. Il considère la déclaration précédente de d et e comme des déclarations non définissantes et, puisqu’elles ont été déclarées int , il n’y a pas de conflit.

En revanche, les déclarations

 pa = &a; pb = &b; 

sont traités comme des déclarations int implicites avec des initialiseurs, mais puisque vous les avez précédemment déclarés comme étant int * , le compilateur se plaint d’une incompatibilité de type.

Remarque: il y a un problème avec votre instruction de sortie.

 printf("%i, %i, %i, %i", pa, pb, d, e); 

Si vous souhaitez imprimer les valeurs entières dans les variables pa par pa et pb , vous devez alors les déréférencer dans l’appel printf :

 printf("%i, %i, %i, %i", *pa, *pb, d, e); 

Si vous souhaitez imprimer les valeurs de pointeur stockées dans pa et pb , vous devez utiliser le spécificateur de conversion %p :

 printf("%p, %p, %i, %i", (void *)pa, (void *)pb, d, e); 

ainsi que la conversion de la valeur du pointeur sur void * (c’est pratiquement la seule fois que vous convertissez explicitement un pointeur sur void * en C).