Pointer Arithmetic: ++*ptr or *ptr++?
Asked Answered
K

3

22

I am learning C language and quite confused the differences between ++*ptr and *ptr++.

For example:

int x = 19;
int *ptr = &x;

I know ++*ptr and *ptr++ produce different results but I am not sure why is that?

Kenna answered 6/3, 2011 at 9:0 Comment(0)
I
54

These statements produce different results because of the way in which the operators bind. In particular, the prefix ++ operator has the same precedence as *, and they associate right-to-left. Thus

++*ptr

is parsed as

++(*ptr)

meaning "increment the value pointed at by ptr,". On the other hand, the postfix ++ operator has higher precedence than the dereferrence operator *. Thefore

*ptr++

means

*(ptr++)

which means "increment ptr to go to the element after the one it points at, then dereference its old value" (since postfix ++ hands back the value the pointer used to have).

In the context you described, you probably want to write ++*ptr, which would increment x indirectly through ptr. Writing *ptr++ would be dangerous because it would march ptr forward past x, and since x isn't part of an array the pointer would be dangling somewhere in memory (perhaps on top of itself!)

Hope this helps!

Isoagglutinin answered 6/3, 2011 at 9:3 Comment(9)
@Isoagglutinin If you would do printf("%d",*ptr++) .It would first print the value at the location contained in ptr and then would increase ptr.Trilobate
@Algorithmist- That's correct; I think my answer covers this. Should I clarify it to make it more explicit?Isoagglutinin
@Isoagglutinin i think * and ++ have the same priority but since their associativity is from L to R this is happening.Do you mean the same when you say ++ binds tighter than *.Trilobate
@Algorithmist- Thanks for pointing that out; you're absolutely correct. I will correct this.Isoagglutinin
*ptr++ is equivalent to *(ptr++) equivalent to *(ptr = ptr + sizeof(datatype))Johnsiejohnson
*ptr++ will be useful , if your ptr is pointing to a string and you want to jump to next char in the string.Axes
@instinct: No, the latter form is not even remotely equivalent to *(ptr++).Urnfield
@instinct Pointer arithmetic accomodates for the size of the pointed-to type, so ptr + sizeof(datatype) will actually move past sizeof(datatype) * sizeof(datatype) bytes. See this example. [Note: Example is compiled as C instead of C++, due to -xc command-line option.]Hettie
As @AnT suggested ptr++ is the same as ptr = ptr + 1 meaning ptr will jump to the next address (that is what adding 1 means in the context of pointers), in particular jump to an address that is sizeof(datatype) bytes away from the starting address. As @Justin Time - Reinstate Monica explained, something like ptr = ptr + 3 would mean to jump to the address which is 3*sizeof(datatype) bytes away. So indeed ptr = ptr + sizeof(datatype) means to jump to the address which is sizeof(datatype) * sizeof(datatype) bytes awayNika
K
14

The accepted answer is not correct. It's not the case that the postfix ++ operator has the same precedence as dereference/indirection *. The prefix and postfix operators have different precedence, and only the prefix operator has the same precedence as dereference/indirection.

As the precedence table shows, postfix ++ has a higher precedence than dereference/indirection *. So *ptr++ gets evaluated as *(ptr++). ptr++ evaluates to the current value of ptr; it increments ptr only as a side effect. The value of the expression is the same as the current value of ptr. So it won't have any effect on the value stored at the pointer. It will merely dereference the pointer (i.e., get the current value stored there, which is 19), then advance the pointer. In your example there is no defined value stored at the new position of ptr, so the pointer is pointing to garbage. Dereferencing it now would be dangerous.

Also as the table shows, prefix ++ has the same precedence as dereference/indirection *, but because of right-left associativity, it gets evaluated as ++(*ptr). This will first dereference the pointer (i.e., get the value stored at the address pointed to) and then increment that value. I.e., the value will now be 20.

The accepted answer is correct about the effects of the two, but the actual mechanism is different from the one given there.

Knuckle answered 29/4, 2016 at 0:52 Comment(4)
This is a better answer than the selected one. Also, Note 2 in precedence table explains why ptr++ evaluates to ptr.Constrict
*ptr returns an l-value. So ++*ptr will absolutely modify the value of the object pointed by ptr (x).Broadtail
Obligatory Linux kernel demonstrationBroadtail
@Broadtail Oops you're right, of course. Sorry and thanks. Edited. Sleepy brain introduced an error into what was a perfectly accurate answer for several months.Knuckle
R
4

As templatetypedef says, but you should provide the parenthesis around *ptr to ensure the outcome. For instance, the following yields 1606415888 using GCC and 0 using CLang on my computer:

int x = 19;
int *ptr = &x;
printf("%d\n", *ptr++);
printf("%d\n", *ptr);

And you expected x to be 20. So use (*ptr)++ instead.

Rubberneck answered 6/3, 2011 at 9:14 Comment(1)
don't you think first printf() should print 19Trilobate

© 2022 - 2024 — McMap. All rights reserved.