2014-09-16 2 views
-29

Étant donné ce codeExplique la sortie de l'extrait suivant?

char *s = "Abbas"; 
printf("%s", s + s[1] - s[3]); 

Pourquoi est-ce la sortie?

bbas 
+10

La sortie doit être '' bbas'', pas '' bhas'' ' –

+1

Son impression est juste ("% s ", s + 1); déguisé;) –

+0

Personne n'a mentionné que 's + s [1] -s [3]' peut mener à un comportement indéfini selon la sous-expression évaluée en premier. Si c'est l'addition, le pointeur résultant est hors limites et UB s'ensuit. (EDIT: [CashCow] (http://stackoverflow.com/a/25870312/947836) fait, en réalité.) – jrok

Répondre

11
char *s = "Abbas"; 
s + s[1] - s[3] 
s + 'b' - 'a' 
s + 1 /* Assuming ascii encoding. Posibly the machine where you tested, (s + 'b') - 'a' = s + 1 */ 
"bbas" 

Pour mieux comprendre imprimer les valeurs suivantes

printf("%c (%d), %c (%d), %c - %c = %d\n", 
    /* ^^^^ ^^^*/ 
     s[1],s[1],s[3],s[3], s[3], s[1],s[3] - s[1]); 
printf("%s - %s - %s", s, s+1, s+2); 

Disposition de la mémoire

+-----+-----+-----+-----+-----+-----+ 
| 'A' | 'b' | 'b' | 'a' | 's' | '\0'| 
+-----+-----+-----+-----+-----+-----+ 
    s s+1 s+2 s+3 s+4 s+5 

EDIT

Comme indiqué dans les autres réponses et commentaires, s+s[1]-s[3] conduit à UB. Pour vous assurer que vous obtenez bbas en sortie, vous devez utiliser parantesis autour expression plus tard: s+(s[1]-s[3])

+0

comme noté sur les autres réponses,' s + 'b' - 'a'' à 's + 1' n'est pas comment C fonctionne; l'association est de gauche à droite –

+0

@MattMcNabb Exactement ce n'est pas comme cela que ça fonctionne. C'est juste pour faciliter l'explication pour que les lecteurs comprennent mieux. (a + b) - c = a + (bc) tant que (b> c ou b et c sont signés positifs) et (a est non signé ou a ne déborde pas), ou en mots simples sur la plupart des systèmes disponible. –

+0

L'arithmétique du pointeur @MohitJain n'est définie que dans l'objet tableau, 's + 'b'' provoque un comportement indéfini. (Votre réponse explique ce qui pourrait arriver sur les systèmes qui utilisent un modèle de mémoire plate et ne piège pas les pointeurs hors limites) –

0

Votre sortie est erronée. sortie sera: bbas Parce que, s pointe sur la base du tableau permet de dire 0x10. et s[1] donne « b » et s[3] donne « un »

0x10 + 'b' -'a' = 0x10 + 1 = 0x11 impression démarre à partir s[1]. alors la sortie sera bbas

1

s pointe vers le début de la chaîne. s[1] est le deuxième élément, c'est-à-dire b et s[3] est le 4ème élément a. Lorsque vous faites s[1]-s[3], c'est-à-dire 'b' - 'a', il fait en réalité de l'arithmétique sur les valeurs ASCII des caractères et 'b'-'a' est 1 dans la table ASCII. Ainsi, vous imprimez à partir de s+1, c'est-à-dire à partir de la 2ème lettre ==>"bbas"

1

En fait, la sortie doit être "bbas"!

s est un pointeur

s + "un certain nombre" signifie que vous déplacez le pointeur vers l'avant

int votre cas: s [1] = 'b' et s [3] = 'a 'qui sera interprété comme des chiffres, basé sur le code ASCI, où' b 'est un pas plus grand que' a ', donc vous allez ajouter +1 à s et sauter la première lettre

3

Le code fait cela parce qu'un char peut convertir en int et vous pouvez ajouter un int à un pointer.

Parce que s[1] est 'b' et s[3] est 'a' et b est probablement 98 et a est 97 que vous faites s+98-97

Ce que je remettrais en question est de savoir si ce comportement est en réalité non définie sans paranthèses. Il me semble que c'est parce que vous ne pouvez pas ajouter 98 à l'adresse s.

Ce serait bien défini: s + (s[1]-s[3]) bien qu'il soit encore horrible.

+0

FYI sur le sujet de UB: http://stackoverflow.com/questions/10473573/why-is-out -of-bounds-pointer-arithmetic-undefined-behavior (merci jrok et MattMcNabb!) – quetzalcoatl

+0

Je me trompe peut-être ici (n'hésitez pas à me le dire si je le suis), mais n'est-ce pas le cas de 's + 98' seulement un problème si vous essayez ensuite de le dé-référencer? Dans ce cas '* ((s + s [1]) - s [3])' est 'valide' (mais toujours absolument écoeurant). – Baldrickk

+0

@Baldrickk regarde la question référencée. s + 98 n'est pas garanti pour être quelque chose de significatif et soustraire 97 à nouveau n'est pas garanti de vous donner s + 1. – CashCow

Questions connexes