Comment se comportent les déclarations de variables?

#include #include int main(){ char i; int c; scanf("%i",&c); scanf("%c",&i);// catch the new line or character introduced before x number printf("%i",i);// value of that character getch(); return(0); } 

Le programme se comportera de la même manière avec les déclarations de variable suivantes au lieu de la déclaration de variable ci-dessus:

ce:

 int c; int *x; int i; 

ou ca:

 int *x; int c; int i; 

Et seulement de cette façon: c variable et un pointeur x avant la variable i . Je sais que ces dernières déclarations n’ont pas de sens, l’ int i au lieu de char i et un pointeur ajouté qui n’est même pas nécessaire. Mais cela s’est produit accidentellement et je me demandais si c’était une simple coïncidence.

L’ordre dans lequel vous déclarez vos variables ne devrait faire aucune différence, en supposant que rien ne se passe mal avec le rest de votre code. L’ordre de déclaration n’a rien à voir avec la façon dont ils sont mis en mémoire. Et même si c’était le cas, vous vous référez aux variables par leur nom; tant que votre code est correct, une référence à i est une référence à i , et le compilateur générera le code nécessaire pour accéder à la variable correctement.

Maintenant, si vous faites ceci:

 int i; scanf("%c", &i); 

alors vous faites quelque chose de mal. scanf au format "%i" nécessite un argument char* , qui pointe sur l’object char dans lequel la valeur sera stockée. Vous lui donnez un int* plutôt qu’un caractère char* . En conséquence, le comportement de votre programme n’est pas défini. la norme linguistique ne dit rien sur son comportement.

Alors, pourquoi semble-t-il fonctionner correctement? Ce qui se passe probablement, c’est que scanf traite l’adresse de l’object int comme un pointeur sur un caractère. Cela indiquera probablement le premier octet de la représentation de i ; Par exemple, i pourrais avoir 32 bits et le pointeur indiquera les 8 premiers de ces bits. (Il peut s’agir des bits de poids fort ou faible, selon le système.)

Maintenant, quand vous imprimez la valeur de i :

 printf("%d\n", i); 

le contenu de i est, par exemple, 1 octet composé du caractère que vous venez de lire et 3 octets de déchets. Ces 3 octets peuvent bien être tous des zéros, mais ils peuvent être n’importe quoi. S’il se trouve que le nombre d’octets erronés est 0 et que le premier octet est l’octet de poids fort (c’est-à-dire que vous êtes sur une machine big-endian ), vous obtiendrez probablement la sortie “correcte”.

Mais ne fais pas ça. Le comportement n’étant pas défini, il peut fonctionner “correctement” pendant des années, puis échouer de manière spectaculaire au pire moment possible.

La leçon à tirer est que C a tendance à supposer que vous savez ce que vous faites. Un grand nombre de constructions ont un comportement indéfini, ce qui signifie qu’elles sont invalides, mais ni le compilateur ni le système d’exécution ne sont tenus de vous informer de l’existence d’un problème. En C, plus que dans la plupart des autres langues, il vous appartient, en tant que programmeur, de bien faire les choses. Le compilateur (et d’autres outils) vous dira quelques erreurs, mais pas toutes.

Et en présence d’un comportement indéfini, l’ordre dans lequel vous déclarez vos variables peut faire la différence. Par exemple, si vous écrivez du code qui lit ou écrit au-delà de la fin d’une variable, le contenu de celle-ci peut être important. Mais ne soyez pas tenté de mélanger vos déclarations jusqu’à ce que le programme fonctionne. Débarrassez-vous du comportement indéfini pour que l’ordre n’ait pas d’ importance.

La solution: ne faites pas d’erreurs en premier lieu. (Bien sûr, c’est beaucoup plus facile à dire qu’à faire.)

Et les conventions de nommage peuvent être utiles. Si vous aviez appelé votre variable char c et votre variable int i plutôt que l’inverse, il aurait été plus facile de savoir qui est qui.

Mais c est un nom raisonnable pour une variable int utilisée pour contenir les valeurs de caractères en entrée – pas pour scanf , mais pour getchar() , comme dans:

 int c; while ((c = getchar()) != EOF) { /* ... */ } 

La fonction attend une séquence de références en tant qu’arguments supplémentaires, chacun pointant vers un object du type spécifié par la balise% correspondante dans la chaîne de format, dans le même ordre. Lire à propos de scanf

Ceux-ci peuvent en outre vous aider:

Je ne comprends pas pourquoi je ne peux pas obtenir trois entrées en c

scanf () laisse la nouvelle ligne char dans la mémoire tampon?

En ce qui concerne la dernière partie de votre question, le nombre de bits de int est toujours supérieur à char , ce qui ne posera pas de problème.