65 votes

Comment fonctionne "while (* s ++ = * t ++)"?

Ma question est la suivante: que fait ce code (extrait de http://www.joelonsoftware.com/articles/CollegeAdvice.html ):

 while (*s++ = *t++);
 

le site dit que le code ci-dessus copie une chaîne mais je ne comprends pas pourquoi ...

cela a-t-il à voir avec les pointeurs?

47voto

Jeremy Ruten Points 59989

C'est équivalent à ceci:

 while (*t) {
    *s = *t;
    s++;
    t++;
}
*s = *t;
 

Lorsque le caractère désigné par t est '\0' , la boucle while se termine. Jusque-là, il copiera le caractère indiqué par t sur le caractère indiqué par s , puis incrémente s et t pour pointer vers le prochain caractère dans leurs tableaux.

34voto

paxdiablo Points 341644

Cela a tellement de choses sous les couvertures:

while (*s++ = *t++);

L' s et t variables sont des pointeurs (presque certainement caractères), s étant la destination. Les étapes suivantes illustrent ce qui se passe:

  • le contenu de t (*t) sont copiés sur s (*s), un caractère.
  • s et t sont à la fois incrémenté (++).
  • l'affectation (copie) renvoie le caractère qui a été copié (à l' while).
  • l' while se poursuit jusqu'à ce que le caractère est égal à zéro (la fin de la chaîne en C).

Effectivement, c'est:

while (*t != 0) {
    *s = *t;
    s++;
    t++;
}
*s = *t;
s++;
t++;

mais écrit dans un beaucoup plus et de façon compacte.

19voto

Chris Lutz Points 34157

Supposons s et t sont char *s qui pointent vers des chaînes de caractères (et d'assumer s est au moins aussi grand que t). En C, les chaînes de tous les fin en 0 (ASCII "NUL"), correct? Qu'est ce que cela à faire:

*s++ = *t++;

Tout d'abord, il n' *s = *t,, copie de la valeur en *t de *s. Ensuite, il n' s++, alors s pointe maintenant vers le caractère suivant. Et puis il ne t++, alors t points au caractère suivant. Cela a à voir avec la priorité de l'opérateur et du préfixe vs postfix incrémenter/décrémenter.

La priorité de l'opérateur est l'ordre dans lequel les opérateurs sont résolus. Pour un exemple simple, regardez:

4 + 2 * 3

Est-ce 4 + (2 * 3) ou (4 + 2) * 3? Eh bien, nous savons qu'il est le premier à cause de la priorité - binaires - * (opérateur de multiplication) a une priorité plus élevée que le binaire + (opérateur d'addition), et est résolu en premier.

En *s++, nous avons unaire * (déréférencement de pointeur de l'opérateur) et unaires ++ (postfix opérateur d'incrémentation). Dans ce cas, ++ a une priorité plus élevée (dit aussi "lier serré") que *. Si on avait dit, ++*s, nous incrémenter la valeur en *s plutôt que de l' adresse pointée par s parce que le préfixe de l'incrément a priorité inférieure* comme déréférencement, mais nous avons utilisé postfix incrément, qui a une priorité plus élevée. Si l'on avait voulu utiliser le préfixe de l'incrément, nous pourrions avoir fait *(++s), depuis la parenthèse aurait remplacé tous en bas de priorités et forcé ++s venir en premier, mais cela aurait l'effet indésirable en laissant un vide de caractères au début de la chaîne.

Notez que juste parce qu'elle a une priorité plus élevée ne signifie pas qu'il arrive en premier. Postfix incrément spécifiquement arrive après la valeur a été utilisé, ce qui à son pourquoi *s = *t qui se produit avant l' s++.

Alors maintenant, vous comprenez *s++ = *t++. Mais ils l'ont mis dans une boucle:

while(*s++ = *t++);

Cette boucle n'est rien - l'action est tout dans la condition. Mais de vérifier que la condition qu'il renvoie "false" si *s jamais 0, ce qui signifie *t a 0, ce qui signifie qu'ils étaient à la fin de la chaîne (yay pour ASCII "NUL"). Si cette boucle tourne tant qu'il y a des caractères en t, et les copies consciencieusement en s, l'incrémentation s et t tout le chemin. Lorsque cette boucle s'arrête, s a été NUL de terminaison, et est une chaîne correcte. Le seul problème est, s de points à la fin. Garder un autre pointeur de la pratique qui pointe vers le début de l' s (c - s avant l' while() boucle) - qui sera votre copié chaîne:

char *s, *string = s;
while(*s++ = *t++);
printf("%s", string); // prints the string that was in *t

Alternativement, regardez ça:

size_t i = strlen(t);
while(*s++ = *t++);
s -= i + 1;
printf("%s\n", s); // prints the string that was in *t

Nous avons commencé par l'obtention de la longueur, de sorte que lorsque nous avons terminé, nous n'avons plus l'arithmétique des pointeurs de mettre s de retour au début, où il a commencé.

Bien sûr, ce fragment de code (et toutes mes fragments de code) ignorer tampon questions pour des raisons de simplicité. La meilleure version est ceci:

size_t i = strlen(t);
char *c = malloc(i + 1);
while(*s++ = *t++);
s -= i + 1;
printf("%s\n", s); // prints the string that was in *t
free(c);

Mais tu le savais déjà, ou vous allez bientôt poser une question sur préférée de tout le monde site web à ce sujet. ;)

* En fait, ils ont la même priorité, mais c'est résolu par des règles différentes. Effectivement ils ont de priorité plus basse dans cette situation.

16voto

tristopia Points 5074
 while(*s++ = *t++);
 

Pourquoi les gens pensent-ils que cela équivaut à:

 while (*t) {
    *s = *t;
    s++;
    t++;
}
*s = *t;                        /* if *t was 0 at the beginning s and t are not incremented  */
 

quand ce n'est évidemment pas.

 do {
   char tmp = *t;
   *s = tmp;
   s++;
   t++;
} while(tmp);
 

est plus comme ça

1voto

Andrew Points 6844

Cela fonctionne en copiant les caractères de la chaîne pointée par ' t ' dans la chaîne pointée par ' s '. Pour chaque copie de caractère, les deux pointeurs sont incrémentés. La boucle se termine lorsqu'elle trouve un caractère NUL (égal à zéro, d'où la sortie).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X