4
#include<stdio.h>

int main()
{
   int *p;
   int arr[]={10,20};
   p=arr;
   ++*p; //expected evaluation = (++(*p))
   printf("arr[0]=%d, arr[1]= %d, p=%d\n",arr[0],arr[1],*p);
}

Output = arr[0]=11, arr[1]= 20, p=11 which is totally fine. But, here

#include<stdio.h>

int main()
{
   int *p;
   int arr[]={10,20};
   p=arr;
   ++*p++; //expected evaluation = (++(*(p++))) = *p->20 , thus ++20 = 21
   printf("arr[0]=%d, arr[1]= %d, p=%d\n",arr[0],arr[1],*p);
}

Since the priority of postfix ++ is higher, the value of a[1] or *p should be 21 but is:

arr[0]=11, arr[1]= 20, p=20

For some reason it doesn't increment? Why?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Mayur Kulkarni
  • 1,306
  • 10
  • 28
  • 11
    _Why_ must you write it that way in the first place? – Jeff Mercado Jul 17 '15 at 03:13
  • I was just reading about a tutorial about pointers which raised me this doubt :') – Mayur Kulkarni Jul 17 '15 at 03:15
  • 7
    Very unnecessary obfuscation. – lhoworko Jul 17 '15 at 03:16
  • 1
    `p++` evaluates to the initial value of `p`... there was a related question a few days ago – Diego Jul 17 '15 at 03:17
  • Ps: Good idea to write readable code. Otherwise it sometimes comes back and bites you – Ed Heal Jul 17 '15 at 03:18
  • 11
    There is _no_ reason you should _ever_ write code like that. Your goal as a programmer isn't to maximize the amount of operations you can perform on a pointer within a single expression... but to write code that both computers _and humans_ can read. If you're going to read about pointers, you should read about sequence points too. Maybe even some questions already on Stack Overflow on other obscure ways to operate on pointers and how stupid it really is. – Jeff Mercado Jul 17 '15 at 03:22
  • I am voting to close this question as this would not help future visitors not the current person asking the question. The person in question should learn to write readable code – Ed Heal Jul 17 '15 at 03:26
  • 9
    Whether or not the code is "readable" isn't the question. This is perfectly acceptable and valid C code, and the op is asking a question about operator behavior. – Jens Jul 17 '15 at 03:31
  • 1
    @Jens - Do not encourage it. It makes bad code and our beloved profession has enough stick to beat itself with. – Ed Heal Jul 17 '15 at 03:32
  • 5
    @Ed: I don't encourage anything. But part of our profession is to read, understand, and maintain code as well and in that context we will sooner or later run into statements like that. It's best to have them documented and explained. – Jens Jul 17 '15 at 03:34
  • ... not written in the first place. Code review?! – Ed Heal Jul 17 '15 at 03:39
  • 10
    Bad code isn't off-topic. – o11c Jul 17 '15 at 03:47
  • 2
    @o11c Bad clde like this should be. SO is not supposed to be a repository of crap. I can assure you that, if I was in a position to do so, I would execute a 'fire immediate' instruction on the OP. Engineers doing debugging/maintenance/enhancement work on such code would be horrified by such garbage and have to rewrite it so that it's functionality is obvious without looking up standards documents. Note well the answer/s - even skilled and experienced SO contributors get misled by this... thing. – Martin James Jul 17 '15 at 06:58
  • 1
    I meta'd this: http://meta.stackoverflow.com/questions/299511/is-bad-code-on-topic – Martin James Jul 17 '15 at 07:18
  • 3
    Bad code is not off topic. But comments saying it's bad code and he shouldn't do stuff like this is perfectly acceptable as well. – Almo Jul 17 '15 at 07:52
  • Related to: [Why are these constructs (using ++) undefined behavior?](http://stackoverflow.com/q/949433/1708801) ... not a duplicate there has to be a good duplicate for this but may take some effort to find it. – Shafik Yaghmour Jul 17 '15 at 12:30
  • @MartinJames lol @ "this... thing." – Morkrom Jul 18 '15 at 01:01
  • Hint: `++*++p` would have done what you expected `++*p++` to do. – zwol Jul 20 '15 at 02:12

2 Answers2

3

Following operator precedence and order of evaluation, the statement ++*p++ will first post-fix increment the pointer p, since the post-fix increment operator has a higher precedence then a dereference.

The result of p++ will return the old value of p and increment p so that it points to 20. Dereferencing the result of the postfix increment (which is a pointer to arr[0]) gives you 10 which is the pre-fix incremented, thus yielding 11.

The end result is an array which contains the values {11,20}, as your output confirms.

Alejandro
  • 3,040
  • 1
  • 21
  • 30
  • @TheParamagneticCroissant: Mind sharing why you think so? – nhahtdh Jul 17 '15 at 10:08
  • 4
    @TheParamagneticCroissant, I haven't been able to find a reference that indicates why modifying a pointer and its pointed-to object w/o a sequence point would yield UB ( in this case). A previous comment here, that appears to have been deleted, mentioned a post about sequence points which I have read through. Perhaps my understanding is still flawed, but `++*p++` gets evaluated first as `*(p++)` which dereferences a copy of the old value of `p`, which is then incremented. I can't see how it matches any of the points mentioned [here](http://goo.gl/lb8N6h) – Alejandro Jul 17 '15 at 13:53
  • 1
    @TheParamagneticCroissant no, this code is correct. `p` and `*p` are different objects. There is no rule about access to different objects requiring a sequencing relation. By your logic the canonical strcpy expression `*p++ = *q++` would be UB. – M.M Jul 18 '15 at 05:55
  • 1
    @TheParamagneticCroissant, I reasoned about the example `a[i] = i++` and completely agree that its UB because there's no way to tell whether the increment to `i` will happen before `i` is used to index into `a` or afterwards. But in this case, it seems, to me atleast, that the timing of the increment of `p` has no bearing on the final result since I'm operating on a copy of the old value of `p` to dereference and increment. The increment to `p` could happen right before I dereference, or even on the next seq. pt `;`, but since I'm working with a copy of `p` , the result is the same. – Alejandro Jul 18 '15 at 14:00
  • 2
    @TheParamagneticCroissant it doesn't matter when the increment is sequenced; the definition of `p++` is that it evaluates to the old value of `p`; and `p` is incremented as side-effect. `*(p++)` dereferences the old value of `p` regardless of when the increment happens. – M.M Jul 18 '15 at 14:38
  • In C++03, `a[i] = i++` is undefined because the side-effect of updating `i` is not sequenced before or after the read of `i` on the left-hand side. But in `++*p++`, `p` is only read once, so there is no second read of `p` to cause trouble. The thing incremented by prefix-`++` is the result of evaluating the lvalue expression `*p++` . You seem to be treating it as something like `foo(*p++, ++*p)` but it isn't. – M.M Jul 18 '15 at 14:46
  • 2
    "One cannot tell whether the modification of the pointer happens before or after the modification of the pointed object" - that's true but it does not make there any undefined behaviour. In `*p++ = 5;` you cannot tell whether the modification of the pointer happens before or after the modification of the pointed-to object either. – M.M Jul 18 '15 at 14:49
  • for "c++03" above, read "c99". There is no essential difference between `*p++ = 5` and `++*p++`. – M.M Jul 18 '15 at 14:52
  • 1
    I'd really appreciate it if the downvoters would please share their reasoning. Sure, I don't agree that the OP code is good/clean/what have you, but it seems the main reason for the downvotes is because there's a debate over whether or not this is UB. So far, only a few people have kindly cared to explain their reasoning. It'd be beneficial for all future readers of this question (since it even got on meta), to please explain the rationale behind your [up|down]vote, since there appears to be a discrepancy – Alejandro Jul 18 '15 at 16:27
0
++*p++;

Is equivalent to:

int* p1 = p++; // p1  points to a[0]. p points to a[1]
++(*p1);       // Increments a[0]

That explains the output.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    Does not explain the input (of the programmer!) – Ed Heal Jul 17 '15 at 03:26
  • @EdHeal, I assume you mean the output of the OP. I think it explains it. – R Sahu Jul 17 '15 at 03:29
  • 1
    .. The input - the thinking of doing it! – Ed Heal Jul 17 '15 at 03:31
  • @EdHeal, you lost me there. – R Sahu Jul 17 '15 at 03:32
  • @EdHeal, I see. The only reason to write such code is to understand how the language works. I hope nobody writes such code in a working project. – R Sahu Jul 17 '15 at 03:39
  • 6
    @TheParamagneticCroissant, I understand that operator precedence and order of evaluation are different aspects of evaluating an expression. If you don't mind, can you explain how a compiler would be able to evaluate that expression differently than what I showed? – R Sahu Jul 17 '15 at 15:07