déclaration de variables portant le même nom que global, local et statique

J’ai l’extrait de code suivant et je dois parsingr quel sera le résultat:

#include  void f(int d); int a = 1, b = 2, c = 3, d = 4; int main(){ int a = 5, c = 6; f(a); f(b); f(c); printf("%d %d %d %d\n",a,b,c,d); return 0; } void f(int d){ static int a = 0; a = a + 7; b = a + d; c++; d--; printf("%d %d %d %d\n",a,b,c,d); } 

La sortie que j’ai est la suivante:

 7 12 4 4 15 26 5 11 21 27 6 5 5 27 6 4 

Cela m’a vraiment dérouté. J’ai remarqué que dans les 3 appels de fonction, le globalement déclaré a souffre de l’affectation et que dans le printf() du corps de main() , le a déclaré dans main() est imprimé. Cependant, je ne suis pas sûr du comportement du rest des variables. Est-ce un comportement indéfini ou est-il réellement logique?

int a = 1, b = 2, c = 3, d = 4; —> Variables globales

 int main(){ int a = 5, c = 6; ---> Shadows the global `a` and `c` 

….

 void f(int d){ static int a = 0; ---> local static variable visible only inside `f` 

Ceci est lié aux scopes d’identificateur de C. La scope d’une déclaration est la région du programme C sur laquelle cette déclaration est visible. Il y a six champs d’application:

  • Identificateurs de niveau supérieur: s’étend du sharepoint déclaration à la fin du fichier de programme source
  • Paramètres formels dans une définition de fonction: s’étend jusqu’à la fin du corps de la fonction
  • Paramètres formels dans les prototypes de fonctions
  • Identifiants de bloc (locaux): s’étend jusqu’à la fin du bloc
  • Étiquettes de déclaration
  • Macros de préprocesseur

Ce qui se passe dans votre programme est appelé surcharge de noms – une situation dans laquelle le même identifiant peut être associé à plusieurs entités de programme à la fois. Il y a 5 classes de surcharge en C (aka namespaces):

  • Noms de macro du préprocesseur
  • Étiquettes de déclaration
  • Balises de structure, union et énumération
  • Noms de composants
  • Autres noms

En C, les déclarations au début d’un bloc peuvent masquer des déclarations en dehors du bloc. Pour qu’une déclaration en cache une autre, les identificateurs déclarés doivent être identiques, appartenir à la même classe de surcharge et être déclarés dans deux scopes distinctes, l’une contenant l’autre.

En gardant cela à l’esprit, dans votre code, les groupes locaux a et c masquent les globes a et c dans main() , et a in f() cache les globaux a . Toutes les autres références manipulent les variables globales.

  void f(int d){ **static int a = 0;** a = a + 7; b = a + d; c++; d--; printf("%d %d %d %d\n",a,b,c,d); } 

C’est vrai que vous avez déclaré une fonction globale int a et globale void f, mais vous avez également déclaré une variable statique a Chaque fois que la fonction a appelé, fonction fait référence à une variable de fonction. si vous voulez éviter ce problème, vous devez créer un pointeur de variable globale et faire référence à la variable globale de la valeur d’une adresse pointée. Comme vous le savez, les variables statiques conservent leur dernière valeur jusqu’à la fin du programme.

la variable de chaque fonction va exactement être placée dans “Stack” sauf si allouée par malloc. Et la variable globale est “Heap”. Je ne suis pas sûr mais si vous désassemblez votre programme, la valeur statique a ira à emstackr et traitée avec les instructions PUSH et POP.

En C / C ++, les identifiants d’une scope donnée masquent les identifiants de la scope externe à partir du sharepoint déclaration .

L’exemple suivant montre ceci:

 #include  const char a[] = "a"; static const char b[] = "b"; void test(const char * arg) { const char c[] = "c1"; printf("1-. a=%sb=%sc=%s arg=%s\n", a,b,c,arg); const char a[] = "a1"; static const char b[] = "b1"; // arg is present in this scope, we can't redeclare it printf("1+. a=%sb=%sc=%s arg=%s\n", a,b,c,arg); { const char a[] = "a2"; const char b[] = "b2"; const char arg[] = "arg2"; const char c[] = "c2"; printf("2-. a=%sb=%sc=%s arg=%s\n", a,b,c,arg); { static const char a[] = "a3"; const char b[] = "b3"; static char arg[] = "arg3"; static const char c[] = "c3"; printf("3. a=%sb=%sc=%s arg=%s\n", a,b,c,arg); } printf("2+. a=%sb=%sc=%s arg=%s\n", a,b,c,arg); } printf("1++. a=%sb=%sc=%s arg=%s\n", a,b,c,arg); } int main(void) { test("arg"); return 0; } 

Sortie:

 1-. a=ab=bc=c1 arg=arg 1+. a=a1 b=b1 c=c1 arg=arg 2-. a=a2 b=b2 c=c2 arg=arg2 3. a=a3 b=b3 c=c3 arg=arg3 2+. a=a2 b=b2 c=c2 arg=arg2 1++. a=a1 b=b1 c=c1 arg=arg 

Cette sortie a du sens.

En C / C ++, les identifiants d’une scope donnée ont la priorité sur les identifiants de la scope externe. Dans ce cas, dans la fonction main, les variables a et c seront utilisées en tant que variables locales et les valeurs restantes b et d en tant que variables globales. De même, dans la fonction void f(int d) , d est le paramètre passé, a sera utilisé comme statique chaque fois que la fonction sera appelée, b et c seront utilisés comme variables globales. Par conséquent, la sortie sera calculée.

Cependant, vous avez affiché une sortie incorrecte. La sortie correcte doit être:

7 12 4 4 14 26 5 11 21 27 6 5 5 27 6 4