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:
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):
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