Affectation de membre de structure provoquant une erreur de syntaxe en dehors d’une fonction

Je souhaite atsortingbuer une valeur particulière à une variable globale (définie par l’utilisateur) dans le langage de programmation C. Quand je fais cela depuis une autre fonction ou un autre, c’est très bien. Mais quand je le fais depuis l’espace global (en dehors de toute fonction), cela donne l’erreur de compilation suivante:

[expected '=', ',', ';', 'asm' or '__atsortingbute__' before '.' token] 

Voici un extrait de code qui pose problème:

 #include  #define MAX_SIZE 5 typedef struct { int val[MAX_SIZE]; int top; }stack_t; stack_t s; s.top = -1; // <== Initialization from here is causing compilation error main() { //s.top = -1; < === Initialization from here is fine printf("s.top =%d\n", s.top); return 0; } 

Mais le même type d’affectation pour les variables entières ne donne pas seulement un avertissement

 #include  int i,j,k,l; k=10; main() { printf("i= %d, j=%dk=%dl=%d\n", i, j, k, l); return 0; } 

Quelqu’un peut-il s’il vous plaît en dire la raison?

L’erreur de l’atsortingbution du s.top n’est pas surprenante. Ce n’est pas une initialisation, mais une affectation, et ce sont des concepts différents en C. Vous ne pouvez pas avoir d’affectations en dehors de fonctions.

La partie intéressante ici est qu’il semble que vous pouvez faire une affectation de la variable entière k. Mais c’est une illusion, car dans ce cas ce n’est pas une mission mais une initialisation!

La ligne

 k = 10; 

est interprété non pas comme une affectation mais comme une définition de variable. Un indice à cela est que GCC indique aux avertissements que “la définition de données n’a pas de type ou de classe de stockage” et que “type est défini par défaut sur” int “dans la déclaration de” k “”. Donc, la ligne pourrait être écrite comme

 int k = 10; 

Comme Matt l’a écrit dans un commentaire ci-dessous, laisser le type de données comme celui-ci semble être une extension de GCC, et non quelque chose que la norme autorise.

(Au fait, activez les avertissements dans votre compilateur et faites attention à eux!)

Mais attendez, il n’y avait pas déjà une définition de k sur la ligne ci-dessus, et vous ne pouvez pas avoir plus d’une définition, n’est-ce pas?

Tout d’abord, rappelez-vous que C établit une distinction entre les définitions et les déclarations. Une définition d’une variable est lorsque vous “créez” la variable et lui donnez éventuellement une valeur initiale. Une déclaration consiste à indiquer au compilateur que la variable existe, ainsi que son nom et son type de données, mais que la définition est ailleurs. Vous pouvez avoir à la fois une définition et une ou plusieurs déclarations de la même variable. Par exemple:

 int xxx = 10; // This is the definition of xxx int xxx; // This is a declaration of xxx int xxx; // Another delaration of xxx 

Mais parfois, le compilateur ne peut pas déterminer s’il s’agit d’une déclaration ou d’une définition, ce qui est interprété comme une “définition provisoire” ou, en d’autres termes, “peut-être une définition, peut-être juste une déclaration, nous déciderons plus tard “. Par exemple:

 int yyy; 

S’agit-il d’une définition de la variable yyy (sans valeur initiale) ou s’agit-il simplement d’une déclaration dans laquelle la définition sera trouvée ailleurs? Le compilateur ne sait pas, il attend donc pour décider et appelle cela une définition provisoire.

Lorsque le compilateur voit votre première déclaration de k (avec les autres variables i, j et l), il est interprété comme une définition provisoire et lorsque cette dernière définition est trouvée, cette définition provisoire de k sera considérée comme une déclaration. pas une définition.

Le code C doit être à l’intérieur d’une fonction. Vous pouvez déclarer un global en dehors d’une fonction mais vous ne pouvez pas écrire une instruction d’affectation en dehors d’une fonction. C’est-à-dire que vous pouvez définir la valeur initiale dans le cadre de la déclaration de la structure, mais vous ne pouvez pas la modifier. Ici, votre déclaration est uniquement le “stack_t s;” ligne.

Tout en C finit par être compilé en symboles au format binary (le format ELF, par exemple). Les symboles ont des noms, les fonctions sont donc appelées morceaux de code et les éléments globaux sont appelés morceaux de données. Il n’y a pas de morceaux “flottants” dans le binary compilé, tout doit passer sous un nom.

Dans le modèle C, le code flottant en dehors d’une fonction n’a pas de sens car C n’a pas d’endroit où exécuter ce code. C n’exécute jamais un fichier de la même manière que bash, python ou javascript; il ne fait que lancer des binarys. Donc, il ne fonctionne que des fonctions nommées. Les fichiers ne sont connus qu’à la compilation et non à l’exécution.

L’initialisation de l’extérieur du main est la raison de cette erreur. Vous pouvez le faire en utilisant comme ceci.

 stack_t s={.top=-1}; 

Cela vous permettra de faire l’initialisation en déclarant. Référez ce lien. ou cela Cela peut être utile.

Il existe des différences entre l’ affectation et l’ initialisation . Vous devriez noter que l’affectation ne peut pas être faite en dehors d’une fonction. La déclaration

 s.top = -1; 

est une affectation et non une initialisation .

C99 et ce dernier fournit l’ initialisation désignée des structures et des tableaux. Ainsi, vous ne pouvez initialiser que le membre top de struct s tant que

 stack_t s = { .top = -1 }; 

et les autres membres seront initialisés à 0 par le compilateur.

Dans l’espace global, vous pouvez uniquement initialiser et déclarer les variables, mais vous ne pouvez pas affecter la valeur aux variables. Dans votre code, vous atsortingbuez la valeur au membre de struct, de sorte que son erreur de projection est la même pour les entiers de votre code ci-dessous.

Essayez le code ci-dessous dans l’espace global et cela fonctionne bien:

 typedef struct { int val[MAX_SIZE]; int top; }stack_t; stack_t s={{},-1}; main() { printf("s.top=%d",s.top); return 0; }