48

Consider:

void foo1(char **p) { *p++; }
void foo2(char **p) { *p += 1; }

and

char *s = "abcd";
char *a = s; 
foo1(&a); 
printf("%s", a); //abcd

but if I use foo2() instead of:

char *a = s; 
foo2(&a); 
printf("%s", a); //bcd

Can someone explain it?

4
  • 22
    Because *p++ is the same as *(p++) Commented Aug 31, 2012 at 19:25
  • 5
    operator precedence
    – chris
    Commented Aug 31, 2012 at 19:25
  • 3
    Also try void foo3(char **p) { (*p)++; } Commented Aug 31, 2012 at 20:34
  • 4
    enjoy your nice question badge :-) Commented Oct 12, 2012 at 3:49

4 Answers 4

97

The key is the precedence of the += and the ++ operator. The ++ has a higher precedence than the += (in fact, assignment operators have the second lowest precedence in C), so the operation

*p++

means dereference the pointer, then increment the pointer itself by 1 (as usually, according to the rules of pointer arithmetic, it's not necessarily one byte, but rather sizeof(*p) regarding the resulting address). On the other hand,

*p += 1

means increment the value pointed to by the pointer by one (and do nothing with the pointer itself).

11
  • 8
    You did such a great job of explaining it, but could you please add in one detail *p++ increments the pointer itself by 1 "unit", so a char pointer might increment by one, while an int pointer might increment by 4, etc, depending on implementation specifics.
    – Edwin Buck
    Commented Aug 31, 2012 at 19:27
  • 4
    @EdwinBuck: I don't really see the relevance, that's just normal pointer arithmetic and not the focus of the question.
    – GManNickG
    Commented Aug 31, 2012 at 19:29
  • 6
    @EdwinBuck whether a pointer is an int or a char, when you increment it, it increases by one. The actual address that represents that pointer may change more than one byte, due to the size of the pointer however. Commented Aug 31, 2012 at 19:30
  • @RichardJ.RossIII We're both right, but we are talking about different 1's. One unit, or sizeof(*p) is still a 1 in some scale, but if you look at the binary value stored in p the actual value is not always going to be "+1" in binary arithmetic.
    – Edwin Buck
    Commented Aug 31, 2012 at 19:41
  • The representation of the pointer, which is the simple memory address in many C implementations, should not be confused with its value, which is its meaning in the C context. p++ does increase the value by one. Its effect on the representation of that value is irrelevant for the purposes of this question, the same way that it is irrelevant that adding 1 to the float 1.f typically changes the representation by 8,388,608. Commented Aug 31, 2012 at 20:10
28

Precedence. The postfix ++ binds tighter than the prefix * so it increments p. The += is at the low end of the precedence list, along with the plain assignment operator, so it adds 1 to *p.

0

Precedence of prefix ++ and * is same. Associativity of both is right to left. Precedence of postfix ++ is higher than both * and prefix ++. Associativity of postfix ++ is left to right.

0

Let's start with *p += 1

I will try to answer this from a bit of a different angle... Step 1 Let's look at the operators and the operands: In this case it is one operand (the pointer p), and we have two operators, in this case * for dereferencing and += 1 for increment. Step 2 which has the higher precedence * has higher precedence over +=


*P++ This one is a bit trickier... maybe even wicked Again we have one operand (p the pointer) and two operators, only now the * for dereference and ++ post increment are of the same precedence. (In some tables the ++ in a post is a higher precedence.)

Step 1 Let's look at the operators and the operands: In this case it is the operand, and you have two operators, in this case * for dereferencing and ++ for increment. Step 2 which has the higher precedence? ++ has higher precedence over * Note: even if they have the SAME precedence they associate right to left, again, the ++ is before * Step 3 (the tricky part...) Where is ++ ? it is to the right side of the operand, which means POST Increment In this case, the compiler take a 'mental note' to perform the increment AFTER it is done with all the other operators... What after means? It means that it will only apply the increment as the very very very last step before the next ';' so it will be done with all other operators that are on the same 'line' note: if it was *++p then it will do it BEFORE any other operator on the same line so in this case, it is as equivalent to taking two of the processor's register, one will hold the value of the dereferenced *p and the other will hold the value of the incremented p++, the reason in this case there are two, is the POST activity... This is where in this case it is tricky, and it looks like a contradiction. One would expect the ++ to take precedence over the *, which it does, only that the POST means that it will be applied only after ALL other operands, BEFORE the next ';' token...

Like I said, the tricky part is that any increment that is to the right of an operand will be set aside, and will be applied as the LAST operation before it moves on to the next line...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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