0
#include<stdio.h>
int main()
{
    char *s[] = { "knowledge","is","power"};
    char **p;
    p = s;
    printf("%s ", ++*p);
    printf("%s ", *p++);
    printf("%s ", ++*p);

    return 0;
}

Output:

nowledge nowledge s

Please explain the output specially output from the 2nd printf() statement.I think that because ++ and * have same precedence therefore in *p++ p should be incremented first and then use *(associativity from right to left for unary operators).

2
  • For reference: in case it wasn't obvious, this code alters s[0] and s[1]. If this array were being passed to you, that'd be a nasty side effect; you'd have made those pointers basically unfreeable. This is part of why i hate combining dereferencing and increments -- it's quite easy to do the wrong thing. :P
    – cHao
    Commented Jun 22, 2012 at 19:54
  • this is really homework? they don't have better things for you to learn? Or is this meant as a bad example, such that you learn not to do things like this? Commented Jun 22, 2012 at 20:58

4 Answers 4

5

first one increments *p and displays the string (setting it to the n in knowldege). second one displays the string *p then increments p (moving it to "is"). third one increments *p then displays the string (which starts at the s in "is").

3

According to C++ Operator Precedence:

  1. "*" has the same precedence as prefix "++" but must be avaluated rigth to left.

    printf("%s ", ++*p);

So first *p is evaluated, then ++(*p), leading to the second character in the first string.

  1. "*" has less precedence than suffix "++".

    printf("%s ", *p++);

So first p is incremented, but it is a post-increment. The value returned from the operation is the original one. This way, the * operates over the original pointer, that pointed to the second char on the first string.

Note that, this time, ++ is operating over p, and not over *p.

  1. Since "2", p points to the second string. When you do ++*p you are now pointing to the second character of the second string ("s"). As you are again using a pre-increment, the value passed to printf is already changed.

    printf("%s ", ++*p);

I may get clearer if you do a little change and print the pointer value aswell (ignore the warnings):

printf("%s [%p]\n", ++*p, p );
printf("%s [%p]\n ", *p++, p );
printf("%s [%p]\n ", ++*p, p );

nowledge [0x7fff6f5519e0]
nowledge [0x7fff6f5519e8]
 s [0x7fff6f5519e8]
2
  • 3
    Nice answer, but aren't those prints UB since you're not guaranteed in what order the function arguments are evaluated?
    – JoeFish
    Commented Jun 22, 2012 at 20:16
  • @JoeFish - Yes, you are right. Those expressions have side effects, and that's why I said to ignore the compiler warnings. In a production code we must not rely in such expressions. Thanks for asking!
    – j4x
    Commented Jun 27, 2012 at 11:21
2

The value that the increment postfix operator (p++) evaluates to is p. The value that the increment prefix operator (++p) evaluates to is p+1.

In your second printf, *p++ evaluates to what *p would evaluate to, but has the side effect of incrementing p.

1

When faced with tricky sequences of operators, it's often easy to rewrite it as a series of simple statements. Your block becomes:

p[0]++;  //skips over the 'k' in knowledge
printf("%s", *p);
printf("%s", *p);
p++;     //moves to the next word
p[0]++;  //skips over the 'i' in is
printf("%s", *p);

Not the answer you're looking for? Browse other questions tagged or ask your own question.