0
int main()
{
    char *p = "ayqm";
    char c;
    c = ++*p++;
    printf("%c",c);
}

I thought it should print 'c' but it prints 'b'. Please explain.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 2
    @usr that is for C++, not C. Also, this is not undefined behavior like in that question (as p itself is not reused). – KillianDS Aug 31 '13 at 17:01
  • It works unexpectedly because it's gibberish. Even if someone can show that it's "legal", it's nothing you should actually code. – Hot Licks Aug 31 '13 at 17:03
  • 1
    I protest: to close this as a duplicate of [Undefined Behaviour and Sequence Points](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points) is an outrageous injustice; the expression is has no undefined behaviour related to modifying the same value twice in a single expression, which is what the other question is about. However, the code in [Find the fault or error](http://stackoverflow.com/questions/17818866/find-the-fault-or-error) does use `++*p++` and tries to modify a literal string — that is a good duplicate. – Jonathan Leffler Aug 31 '13 at 17:20

3 Answers3

3

It's due to operator precedence, it makes the postfix ++ operator increase the pointer and not the dereferenced value.

So your expression returns the first 'a' which is increased by the prefix increase to 'b', but due to the above mentioned operator precedence the postfix increase is actually for the pointer.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
3

The expression can be broken down as follows, which can clarify what happens.

c = ++*p++;

steps:

1) (*p)         // (*p) == 'a'
2) ++(*p)       // (*p) == 'b'
3) c = (*p)     // c == 'b'
4) p++          // p -> 'y'

EDIT : edited to clarify modification of (*p) per comments

Ziffusion
  • 8,779
  • 4
  • 29
  • 57
  • 2
    Is this even defined behavior? The sequence of actions seems undefined. – usr Aug 31 '13 at 17:20
  • I believe that, in this case, the operator precedence, and binding rules apply clearly enough for it not to be undefined behavior. – Ziffusion Aug 31 '13 at 17:22
  • 2
    `c = ++*p++` is completely defined behaviour as long as `p` points to modifiable data. In the question, it points to a string literal which may not be modified; however, avoiding that problem is simple (`char a[] = "ayqm"; char *p = a;`) and the expression is then 100% legitimate — albeit something that should not be used in reviewed codein the ordinary course of business. – Jonathan Leffler Aug 31 '13 at 17:23
  • I don't think that's correct. The value of `*p++` ought to be incremented as well. `p` now correctly points at `'y'` but the value of `'a'` should be a `'b'`, too. But your steps do not reflect this. – bitmask Aug 31 '13 at 17:24
  • @usr I think Ziffusion means *`can be`* broken down. Yes it is undefined as it also modify const string literal – Grijesh Chauhan Aug 31 '13 at 17:25
  • @bitmask: you're correct that the string is modified to become `"byqm"` (as well as `c` containing `'b'`). – Jonathan Leffler Aug 31 '13 at 17:25
  • @JonathanLeffler Is the expression: `++*p++;` same as `++p[i++]` not undefined ? – Grijesh Chauhan Aug 31 '13 at 17:27
  • 1
    @GrijeshChauhan: Under what circumstances do you think `++p[i++]` is undefined behaviour? Assuming `p` and `i` are not aliassed in some contorted way, and `i` is appropriately initialized to an index in the range of the array of objects pointed to by `p`, the expression `++p[i++]` is perfectly well-formed and completely defined behaviour. If `i` is too large (or too small), or `p` points to readonly data, then you have problems; otherwise, it is fine. The proscribed behaviour is modifying a single value twice between sequence points, as in `a[i++] = ++i;`, etc. – Jonathan Leffler Aug 31 '13 at 17:43
0

Here postfix has the highest precedence but it will the effect the value only after the statement. ++ and * have same precedence, and they have right associativity. There for it will work like this:

*p -> evaluates to a

then ++'a' which evaluates to 'b'

dvai
  • 1,953
  • 3
  • 13
  • 15