0
votes

Variables de portée globale et locale (Pourquoi la deuxième impression 28 est-elle ici?)

#include <stdio.h>

int i = 3, j = 10;

int crypt(int j)
{
  return (i = i+j);
}

void decrypt(int x, int i)
{
  j += crypt(i);
}

int main(void)
{
  int i = 0;
  i = crypt(5);
  decrypt(i, j);
  printf("|%d %d|", i, j);
  return 0;
}
I'm having trouble figuring out why does it printout |8 28|.The "8" part, I understand that ati = crypt(5) -> j is now 5 in this function -> i = i + j -> There's no i therefore it uses the global variable i = 3 -> i = 3 + 5 -> returns i = 8So the i in the main function becomes 8.But what about the next printout? Why is it 28 instead of 23?The way I read it was like thisdecrypt(i, j) -> decrypt(8, 10) -> x is now 8 and i is now 10 in this function -> j += crypt(i) -> j += crypt(10) -> j in this function is now 10. return ( i = i + j ), there's no i in this function so i = 3 + 10... returns 13?So then j += 13 is 23? Which part of the step did I mess up? I've been reading local / global scope online and I still don't quite get where did I go wrong... Feels like I'm messing up my value for i somewhere. PS: I apologize for the poor formatting, not quite sure how else can I put it cleanly. 

6 commentaires

essayez de compiler avec -Wshadow , si vous utilisez gcc.


Vous oubliez le devoir dans i = i + j . Lors du deuxième appel à crypt , la valeur du i global n'est plus 3 .


return (i = i + j), il n'y a pas de i dans cette fonction donc i = 3 + 10 ... renvoie 13? Vous avez déjà changé le i global en < code> 8 lors de l'appel précédent à crypt. Donc i vaut 8 maintenant


Et tout cela explique pourquoi jouer avec les globaux et les cacher partiellement chez les locaux est si dangereux ...


Comme l'a dit @SergeBallesta, c'est une mauvaise pratique. Le compilateur ne vous a-t-il pas averti que les variables locales cachaient les globaux? Sinon, examinez l'activation des avertissements du compilateur. Ils vous éviteront beaucoup de chagrin à l'avenir.


Merci beaucoup, je vais essayer de changer mes paramètres de compilateur.


4 Réponses :


1
votes

Vous écrivez:

return (i = i + j), il n'y a pas de i dans cette fonction donc i = 3 + 10 ... renvoie 13?

Non, i n'est plus 3. Il a été changé en 8 précédemment, c'est-à-dire ici return (i = i + j); en raison du premier appel de crypt

Lorsque vous écrivez:

Ainsi, le i dans la fonction principale devient 8.

c'est correct, mais le i global a également été modifié.


1 commentaires

Ahh merci! Je vois où je me suis trompé. J'ai complètement oublié le (i = i + j) affectant la variable globale.



0
votes

Vous avez ici un i et un j globaux, et un i var local. Dans l'ensemble, chaque fois que vous faites référence à i, il vérifie d'abord votre portée actuelle - ainsi, tout changement sera effectué sur votre i local, et le i global ne changera pas. si vous demandez à une fonction en dehors de main de faire quelque chose avec i var, elle vérifie d'abord sa propre portée, puis vérifie si global i var. dans ce cas, les modifications qui seront apportées sont sur le i global.

Alors ... première fois-

local i est défini dans main puis reçoit la valeur de i = crypt (5); une autre chose est que dans cette fonction, vous attribuez également la valeur 8 au i-> global (i = i + j), avant de renvoyer la valeur 8 au i local.

deuxième fonction:

décrypter (i, j); ici, vous envoyez le i local (= 8) et le j global (= 10) à la fonction, dans lequel vous avez:

j + = crypt (i);
ce qui vous donne j = j + ((global) i = 8 + 10): 10 + 8 + 10. et définissez également votre i global sur 18.


0 commentaires

0
votes

Les variables globales sont déclarées en dehors de toute fonction et peuvent être accédé (utilisé) sur n'importe quelle fonction du programme. Les variables locales sont déclaré à l'intérieur d'une fonction, et ne peut être utilisé qu'à l'intérieur de cette fonction. Il est possible d'avoir des variables locales avec le même nom dans des fonctions.

Au premier appel de la fonction crypt (5); vous avez modifié la valeur de la variable globale en,

i = i + j ----> i = 3 + 5 ----> i = 8

Et lorsque la fonction decrypt () est appelée, i = 8 Parce que i est 8 j imprime 28 après l'addition qui est une variable globale.

Vous pouvez voir comment la mémoire est allouée dans C


0 commentaires

0
votes

Considérez la version suivante du code, où les variables ont été renommées pour éviter toute confusion.

#include <stdio.h>

int iGlobal = 3, jGlobal = 10;

int crypt(int jParam)
{
  return (iGlobal = iGlobal+jParam);
}

void decrypt(int xUnused, int iParam)
{
  jGlobal += crypt(iParam);
}

int main(void)
{
  int iLocal = 0;
  iLocal = crypt(5);
  decrypt(iLocal, jGlobal);
  printf("|%d %d|", iLocal, jGlobal);
  return 0;
}

Maintenant, il devrait être relativement facile d'expliquer ce qui se passe lorsque le code est exécuté:

  1. Dans main () , iLocal est zet à 0
  2. main appelle crypt(5)
  3. crypt évalue iGlobal + jParam , c'est-à-dire 3 + 5, et attribue le résultat à iGlobal , c'est-à-dire iGlobal code > vaut 8
  4. crypt renvoie 8
  5. main attribue la valeur de retour de 8 à iLocal
  6. main appelle decrypt(8,10)
  7. décrypter les appels crypt(10)
  8. crypt évalue iGlobal + jParam , c'est-à-dire 8 + 10, et attribue le résultat à iGlobal , c'est-à-dire iGlobal code > a 18 ans
  9. crypt renvoie 18
  10. decrypt ajoute la valeur de retour de 18 à jGlobal , c'est-à-dire que jGlobal est 28
  11. printf imprime les valeurs de iLocal , 8 et jGlobal , 28

La partie compliquée, le cas échéant, est de savoir quand les variables globales sont remplacées (a.k.a. cachées, ou ombrées) par leurs homologues locaux, la réponse étant "chaque fois que possible".


0 commentaires