Quelle sera sa sortie et pourquoi?

Je passais en revue les questions relatives aux règles de la scope et à toutes ces questions, puis j’ai obtenu un extrait de code ci-dessous:

#include  int main() { int x = 1, y = 2, z = 3; printf(" x = %d, y = %d, z = %d \n", x, y, z); { int x = 10; float y = 20; printf(" x = %d, y = %f, z = %d \n", x, y, z); { int z = 100; printf(" x = %d, y = %f, z = %d \n", x, y, z); } } return 0; } 

Si je change la dernière impression en:

 printf("x = %d, y = %d, z = %d \n", x, y, z); 

Je reçois la sortie suivante, que je ne comprends pas: (lien Ideone)

 x = 10, y = 0, z = 1077149696 

Alors, pourriez-vous expliquer pourquoi z affiche cette valeur?

x, y et z sont résolus à la plupart des définitions locales.

Lorsque vous utilisez un spécificateur printf% incorrect, le comportement n’est pas défini.

y est float mais vous utilisez% d pour l’imprimer (dans la dernière ligne).

printf utilise varargs et une fois que vous avez corrompu la stack en utilisant un spécificateur incorrect (% d au lieu de% f dans ce cas), la stack est corrompue et une interprétation incorrecte des données de la stack (avec un décalage incorrect) provoquerait de nombreuses sursockets douloureuses.

Décoder cet UB

C’est ce qui pourrait se passer sur votre machine (une explication possible). En raison de la promotion de l’argument par défaut , le modèle de bits (en hexadécimal) 0x4034000000000000 est en train d’être mis dans la stack pour 20.0f. Sizeof int sur votre machine little-endian est de 4 octets. Lorsque vous imprimez float en tant qu’int, votre machine 0x00000000 est consommée et interprétée en tant qu’int qui imprime en premier 0 %d , puis %d utilise 0x40340000 et l’interprète en tant qu’int.

Mais ne vous fiez jamais à cela et écrivez toujours un code dont le comportement est bien défini.

@ mohit-jain est correct.

L’utilisation d’un spécificateur de format incorrect génère une interprétation de paramètre incorrecte sur la stack, ce qui entraîne un comportement non défini et spécifique au compilateur.

Notez que sur un compilateur moderne, comme gcc ou clang, il se plaindra que votre spécification de format est erronée:

 $ clang test.c test.c:12:54: warning: format specifies type 'int' but the argument has type 'float' [-Wformat] printf(" x = %d, y = %d, z = %d \n", x, y, z); ~~ ^ %f 1 warning generated. 

z = 1077149696
Utiliser% d pour imprimer des valeurs flottantes est un comportement indéfini.
Utilisez “% f” à la place

  1. Toutes les variables que vous avez utilisées ont un type de stockage “Auto” ou “Automatique”.
  2. La scope de la variable automatique se situe à l’intérieur du bloc dans lequel elle est déclarée.
  3. S’il y a des blocs nesteds, la variable déclarée dans le bloc le plus externe sera visible par tous les autres blocs.
  4. Si un bloc a une variable déclarée qui correspond à celle déclarée dans les blocs externes, il écrasera la variable externe “dans son bloc”, c’est-à-dire (localement).

En résumé: Les variables automatiques sont locales au bloc dans lequel elles sont déclarées.