2010-02-21 7 views
2

ok donc si nous avons un char *hello - ands la chaîne est "hello"Coincé avec la syntaxe dans c - pointeurs

et je ne

char *ptr ; 
ptr = hello; 

alors ptr pointera à 'h', correct?

Maintenant, je viens de faire un assignmnet dans ce domaine et complété en utilisant les termes suivants

si je voulais déplacer le pointeur à l'autre chatachter je voudrais juste faire ptr++. Si je voulais utiliser la valeur du pointeur pour une vérification, j'utiliser if(*ptr == '\0')...

Quand je faisais les assignmnets notre professeur nous a donné quelques méthodes de pré construits, et ils ont utilisé des trucs comme

*string++ = *s++; 

ok , alors pourquoi voudrions-nous faire *string (qui obtient une valeur) - et le combiner avec ++

j'espère que je fais pour expliquer ce sence n'est pas clair. Sa juste que je réussi ot faire toute assignmnet avec ptr ++ pour passer à l'élément suivant ou * ptr pour vérifier sa valeur

grâce

+0

@leo J'ai supposé '' bonjour ''est un littéral de caractère, donc je l'ai mis entre guillemets. S'il s'agit d'un nom de variable, les citations ne sont bien sûr pas nécessaires (mais alors votre première question n'a pas beaucoup de sens). –

+0

juste essayé de l'éditer pour faire plus de sens – leo

Répondre

5

L'idiome *s++ signifie "prendre la valeur pointée, et passer à la suivante". De cette façon, vous pouvez effectuer vos opérations de vérification en boucle. L'affectation *p++ = *q++ copie la valeur de *q à l'emplacement indiqué par p et passe à la fois à p et à q, de sorte que la prochaine fois que vous exécutez *p++ = *q++, le caractère suivant sera copié derrière le premier. Etc.

+1

@Vlad, vous avez eu votre p/q autour du mauvais chemin. J'espère que cela ne vous dérange pas. – paxdiablo

+0

@paxdiablo: merci! – Vlad

4

Pas tout à fait. Dans votre question initiale, ptr serait défini pour pointer sur le même premier caractère que hello, qui peut pas nécessairement être h. Vous avez peut-être fait:

char *hello = "goodbye"; 

auquel cas les deux hello et ptr soulignerons que g. Toutefois, votre édition, il est désormais clair que vous vouliez dire:

char *hello = "hello"; 

Votre commentaire sur ptr++ est correcte. Il va déplacer ptr afin qu'il pointe vers le caractère suivant et, conformément à la convention de gestion de chaîne C, '\0' marque la fin de la chaîne.

La déclaration:

*string++ = *s++; 

est quelque chose que vous voyez souvent dans le code de copie de chaîne (copie s-string), quelque chose comme:

char *mystrcpy (char *d, char *s) { 
    char *d2 = d; 
    while (*s != '\0') 
     *d2++ = *s++; 
    *d2 = '\0'; 
    return d; 
} 

Dans ce cas, la ligne *d2++ = *s++; signifie:

  • copier le caractère à s à l'emplacement de la mémoire d2.
  • incrémenter d2 pour pointer sur le caractère de destination suivant.
  • incrémenter s pour pointer vers le caractère source suivant.

En d'autres termes,

*string++ = *s++; 

est fonctionnellement identique à:

*string = *s; 
string++; 
s++; 
+0

a fait une erreur - je voulais un * char appelé bonjour qui représentait la chaîne "bonjour" – leo

0

alors ptr pointera sur h, correct?

Oui. Non. Voir @paxdiablo's answer.

*string++ = *s++;

Cette déclaration peut être considérée comme

*string = *s; 
string ++; 
s ++; 

Cela signifie:

  1. Copiez le caractère s à l'endroit indiqué par string.
  2. Déplacez à la fois s et string vers le caractère suivant.
1

alors pourquoi voudrions-nous faire * string (qui obtient une valeur) - et le combiner aveC++

Lorsque *string est sur le côté gauche des égaux, il doesn 't obtenir la valeur, il définit la valeur.

La déclaration *string++ = *s++; équivaut à:

*string = *s; 
s++; 
string++; 

C'est parce que x++ est le postfix increment operator (par opposition à ++x qui est l'opérateur d'incrémentation préfixe). Le pointeur x est mis à jour mais la valeur que x pointait à l'origine est utilisée dans l'expression.

Personnellement, je dirais que le one-liner est plus déroutant à lire et vous devriez généralement essayer d'éviter les expressions complexes avec des effets secondaires. Mais dans ce cas, c'est un idiome assez standard en C, donc vous pourriez aussi bien vous y habituer.

+0

afin que je puisse atteindre les mêmes résultats avec ma version des étapes décomposées? – leo

+0

Oui, vous n'avez pas besoin de tout faire sur une ligne - vous pouvez le diviser. Mais vous devez être très prudent pour comprendre comment fonctionnent les opérateurs d'incrémentation avant et après le correctif pour ce type de code. C'est facile de faire une erreur. –

+0

merci Mark, je travaille dur pour comprendre cela, au moins le module C est plus compréhensible que celui d'Haskell: D – leo

0

alors ptr pointera sur h, correct?

Oui, correct.

ok, alors pourquoi voudrions-nous faire * string (qui obtient une valeur)

Le « * » ne reçoit pas nécessairement une valeur: il peut définir une valeur, selon la côté du signe '=' c'est.

char *ptr; 
ptr = "hello"; 
char firstLetter = *ptr; //get the value: now firstLetter contains 'h' 
*ptr = 'w'; //set the value: now ptr is pointing to "wello". 

La combinaison * aveC++ signifie que vous faites un après l'autre:

  • Sur le côté droit, '* s ++ signifie « obtenir la valeur à laquelle s est pointage, et puis incrémenter le pointeur s ".
  • Sur le côté gauche, '* chaîne ++' signifie "définir la valeur vers laquelle pointe la chaîne, puis incrémenter le pointeur de chaîne".

En les combinant dans une seule déclaration simplement une façon d'écrire plus court, plus compact (mais fonctionnellement équivalent):

*string = *s; 
string++; 
s++; 
0

Juste un plus rapide à la réponse de Mark Byers, qui souligne à juste titre le postfix increment ("a ++") par opposition à l'incrément de préfixe ("++ a").

Vous voulez probablement jeter un coup d'œil aux C operator precedence pour l'ordre dans lequel les opérateurs sont gérés dans une expression.

Vous pouvez toujours forcer la précédence souhaitée en utilisant des parenthèses: (a + b) * c! = A + b * c.