Analysons-le de manière sèche mais profonde !
Ou comme dirait D. Ritchie : Faisons-le avec la puissance du langage d'assemblage et la commodité du langage d'assemblage.
Je vais essayer d'expliquer tous les aspects nécessaires en me référant à la norme ISO/IEC:9899 (c'est moi qui souligne) - C99. (Le style du post est motivé par la phrase de Donald Knuth "La science est ce que nous comprenons suffisamment bien pour l'expliquer à un ordinateur. L'art est tout ce que nous faisons par ailleurs. " )
Tout d'abord, examinons ce qu'est exactement la for
-La boucle est censée faire !
Se référer à la norme ISO/IEC:9899 6.8.5 "Déclarations d'itération".
Sémantique
4 Une instruction d'itération entraîne l'exécution répétée d'une instruction appelée corps de boucle jusqu'à ce que l'expression de contrôle soit égale à 0 .
Jusqu'ici, rien de nouveau, je suppose, alors allons-y :
6.8.5.3 L'instruction for
1 La déclaration for ( clause-1 ; expression-2 ; expression-3 ) statement
se comporte comme suit : L'expression l'expression-2 est l'expression de contrôle c'est-à-dire évalué avant chaque exécution du corps de la boucle. ...
Donc nous savons maintenant que le corps (dans votre cas // Code
) sera exécuté tant que la valeur préalablement évaluée de votre *p
est différent de zéro.
... L'expression l'expression-3 est évaluée comme une expression vide après chaque exécution du corps de la boucle. [...]
Donc, maintenant nous savons, (je suppose que creuser jusqu'à p++
n'est pas nécessaire ?!) que pour chaque itération p
par incréments, de sorte qu'il peut y avoir un changement de *p
.
Le point suivant n'est pas lié, mais je l'ajoute car il fait de la partie sémantique de l'accord un élément important de l'accord. for
complet et son bien de savoir depuis sa la raison, pourquoi for(;;)
est une inf-boucle.
2 (---) La clause-1 et l'expression-3 peuvent être omises. Une expression-2 omise est remplacée par une constante non nulle.
Ok, c'est la partie sèche mais enrichie d'informations de ce que la for
La boucle le fait dans votre cas.
Passons maintenant à l'arithmétique des pointeurs :
6.5.6 Opérateurs additifs
Contraintes
2 Pour l'addition, soit les deux opérandes doivent être de type arithmétique, soit un opérande doit être un pointeur vers un objet et l'autre doit être de type entier. ( Incrémenter est équivalent à ajouter 1. )
Dans votre cas, vous ajoutez donc 1 (entier) au type "pointeur vers un objet".
Qu'est-ce qui équivaut à augmenter l'adresse de la taille de son type pointé comme le montre cette image de tomislav kostic :
Maintenant, voyons ce que *p
le fait réellement.
6.5.3.2 Opérateurs d'adresse et d'indirection
Contraintes
[...]
2 L'opérande de l'opérateur unaire * doit être de type pointeur.
Sémantique
[...]
4 L'opérateur unaire * indique l'indirection. Si l'opérande pointe vers une fonction, le résultat est un désignateur de fonction ; si il pointe vers un objet, le résultat est une lvalue désignant l'objet. . Si l'opérande a le type ''pointeur vers le type'', le résultat a le type ''type''. Si une valeur invalide a été attribuée au pointeur, le comportement de l'opérateur unaire * est indéfini.
C'est encore un peu sec. 1 mais pour mieux comprendre, on peut faire de l'ingénierie inverse :
6.5.2.1 Subscription de tableau
[...]
Sémantique
2 Une expression postfixe suivie d'une expression entre crochets [] est une désignation en indice d'un élément d'un objet tableau. La définition de l'opérateur d'indice [] est que E1[E2] est identique à (*((E1)+(E2))) .
Así que *((p)+(0))
ce qui est (depuis p+0
est identique à p
... évident) est égal à p[0]
ne fait rien d'autre que d'évaluer p
de l'objet.
Et comme nous le savons, expression-2
d'une boucle for est d'interrompre l'itération si elle évalue 0
on peut dire que c'est la même chose que p[0] != 0
.
Maintenant, la dernière étape
Regardons simplement l'ami du codeur ; JSSCA ... Non, attendez... notre ami a été appelé... ASCII Maintenant que c'est clarifié, nous pouvons comprendre ce que le 0
représente.
C'est le jeton NULL qui, en C, désigne la fin d'une chaîne de caractères.
Si concluant :
Tout ce qu'on fait, c'est :
Iterating the body of that for
-boucle, jusqu'à p
pointe en fait vers l'adresse, où l'objet est évalué comme le jeton de fin de chaîne.
Ou :
Soit p
parcourir la chaîne jusqu'à ce que la fin soit atteinte.
Et maintenant, juste pour me citer moi-même, quelque chose que vous ne devriez jamais oublier :
(souligné par moi.....)
Une variable est déclarée par le biais d'un déclarateur( spécificateur de type ) qui précède l'identifiant qui nomme un objet lvalue qui peut être évalué à sa valeur
Ce n'est ni plus ni moins !
1 C'est-à-dire, ce que j'ai promis ! ;)