Portée des macros en C?

Comment ces macros sont évaluées?

# define i 20 void fun(); int main(){ printf("%d",i); fun(); printf("%d",i); return 0; } void fun(){ #undef i #define i 30 } 

donne la sortie en 2020 mais alors que,

 # define i 20 void fun(){ #undef i #define i 30 } int main(){ printf("%d",i); fun(); printf("%d",i); return 0; } 

donne la sortie en 3030. S’il vous plaît expliquer Merci.

Le préprocesseur fonctionne de haut en bas indépendamment des appels de fonction. Il est effectif à partir de ce point (ligne) quel que soit le fichier dans lequel la macro est définie, jusqu’à la fin de l’unité de traduction correspondante.

Alors, votre code deviendrait,

 # define i 20 // from now on, all token i should become 20 void fun(); int main() { printf("%d",i); // printf("%d",20); fun(); printf("%d",i); // printf("%d",20); return 0; } void fun() { #undef i // from now on, forget token i #define i 30 // from now on, all token i should become 30 } 

Votre deuxième code deviendrait,

 # define i 20 // from now on, all token i should become 20 void fun() { #undef i // from now on, forget i #define i 30 // from now on, all token i should become 30 } int main() { printf("%d",i); // printf("%d",30); fun(); printf("%d",i); // printf("%d",30); return 0; } 

Il n’y a aucune scope impliquée du tout. Les macros sont traitées séparément et indépendamment de la phase de compilation au stade du prétraitement et n’ont aucune notion de scope C. Vos exemples pourraient tout aussi bien être:

 #define i 20 void fun(); int main() { printf("%d",i); fun(); printf("%d",i); return 0; } void fun() { } #undef i #define i 30 

Et:

 #define i 20 #undef i #define i 30 void fun() { } int main() { printf("%d",i); fun(); printf("%d",i); return 0; } 

Vous pouvez voir à partir de ceux-ci pourquoi il se comporte comme il le fait.

Il n’y a tout simplement pas de scope.

Les macros sont remplacées par le préprocesseur. Donc, leur expansion est définie par leur position dans la source, de haut en bas.

Les macros de préprocesseur n’ont pas de scope, car elles ne font pas partie du langage C. Au lieu de cela, c’est une sorte de programme de remplacement de recherche exécuté avant que le compilateur ne s’exécute correctement.

Le préprocesseur consulte simplement n’importe quel fichier, ne doit pas nécessairement être un fichier source C et, lorsqu’il trouve une invocation de macro, il le remplace simplement par le texte figurant dans le corps de la macro.

Les macros prennent effet sur le texte de la source, à un stade distinct avant la compilation. Les macros n’existent plus sous aucune forme dans le code compilé et elles ne sont pas évaluées au moment de l’exécution.

Quelle que soit la définition de macro en vigueur lors de l’appel de la macro (lors d’un balayage textuel de la source), elle sera remplacée par le texte source.

Les symboles de préprocesseur ont très certainement une scope, mais cette scope n’interagit pas avec les autres étendues telles que la scope du fichier.

La scope des symboles du préprocesseur est limitée à une seule unité de traduction. Une #define dans une unité de traduction n’a aucune incidence sur une autre unité de traduction.

La scope d’un symbole de préprocesseur est la région des jetons suivant la directive qui #defines ce symbole. Par la suite, les occurrences de la macro sont reconnues et développées conformément aux règles en vigueur. Les définitions de macros du préprocesseur ne sont pas récursives. Si la séquence de jeton de remplacement contient des invocations du symbole en cours de définition, celles-ci ne sont pas reconnues comme telles. C’est pourquoi la scope commence après la directive. Cependant, cela rest vrai quand une macro est redéfinie; une redéfinition est spéciale et doit être conforme à la règle selon laquelle elle est identique à la définition d’origine. (Les règles précises pour la similitude sont dans la norme).

La scope d’un symbole de préprocesseur se termine à la fin de l’unité de traduction, ou avant si elle est soumise à une directive #undef .

Ainsi, la scope d’un symbole de préprocesseur est essentiellement la région du texte de l’unité de traduction, considérée comme un flot de jetons de préprocesseur, dans laquelle ce symbole est éligible à la reconnaissance et à la substitution.

Les macros sont évaluées lors de l’étape du préprocesseur. L’étape de préprocesseur C se déroule séparément de l’étape de compilation. De ce fait, les macros ne suivent pas la scope habituelle. Ils sont plutôt évalués dans l’ordre dans lequel ils apparaissent dans le fichier source (donc de haut en bas).

Dans votre premier exemple de code, il affiche 2020, malgré l’appel de fun () dans la fonction principale qui devrait modifier la valeur de i en 30, mais comme la fonction fun apparaît en dessous de l’endroit où elle a été appelée, la valeur ne change pas en tant que pré-processeur n’a pas encore atteint ce point.

Dans votre deuxième exemple de code, il génère 3030 car la fonction amusante est au-dessus de la fonction principale. Par conséquent, le contraire se produit car le préprocesseur est déjà passé par la fonction fun et a changé la valeur de i en 30