Pointers: Difference between *p++ as lvalue and rvalue - c

So I am confused about one thing about pointers. Lets look at this:
*p++
I know that operator ++ is "bigger"(sorry idk how else to say, i am not native english speaker) than operator *. So that means that *p++ is in fact percieved as *(p++). So what confuses me is differenet outcome when *p++ is used as lvalue and rvalue. For example:
If I want to sum all elements of array this will work fine(used as rvalue):
sum += *p++;
My question here is why this it first happens *p and then p++, when ++ is bigger then *. Why it wouldnt first happen p++ and then *p.
But if i use it as lvalue, it works as I expected to do. For example:
*p++ = round(*p * 100) / 100;
It first happens p++ and then this new number is given to *p.
Why these 2 thing are different, when it is used as rvalue and lvalue, i mean i am confused why this example with sum.
Thanks :)

Postfix ++ has higher precedence than unary *, so *p++ is parsed as *(p++). In other words, you are applying * to the result of p++.
The result of p++ is the current value of p. As a side effect, p is incremented by 1. With pointers, this means that p is updated to point to the next object in a sequence. IOW, if you have this situation:
+---+---+---+---+
| | | | |
+---+---+---+---+
^
+---+
|
+---+
p: | |
+---+
then after executing p++ (or p = p + 1), you will have this:
+---+---+---+---+
| | | | |
+---+---+---+---+
^
|
|
+---+
p: | |
+---+
This is true regardless of the type of the objects in the sequence, so the address value stored in p may be incremented by more than 1.

The precedence of operators tells us how to structure an expression. Parentheses can be used to show the structure, so sum += *p++ is sum += (*(p++)).
When evaluating the expression, we use the meaning of each operator, also called its semantics.
The meaning of postfix ++, as in p++, is “Do two things, separately: Get the current value of the operand and use that as the value of this expression. And increment the operand.” Thus, with p++, the value of the expression is p, and separately p is incremented. The increment does not affect the value of the expression; it is p before the increment occurs.
The meaning of unary * is “Dereference the pointer.” So the result of *(p++) is *p, which is the object p points to (without the increment).

Related

Are these examples correct?

In this youtube video, I came across with the following examples:
However, they doesn't seem correct to me, for the first example:
*ptr++
In my understanding, this means that, if ++ has greated precedence than *, increment the pointer by 1 in pointer arithmetic, then get the value stored in the address which is pointed by this new pointer. So the code
x = *ptr++;
should be equal to,
ptr++;
x = *ptr;
Which is either conflicting with the video, or I am mixing somethings. Can you please tell me if I am right or wrong?
Precedence affects how expressions are structured. It does not affect what the rules of the operations are.
In *ptr++, precedence says the rules for ++ are applied to ptr, and then the rules for * are applied to the result.
The rules for ++ say that, with ptr++, the resulting value is that of ptr when the operation starts and, separately, the value of ptr is incremented. The actual increment of ptr in memory may occur before, during, or after the production of the result value, but it does not affect the value: The value produced is always the value of ptr before the increment, regardless of when the increment actually occurs.
The rules for * say the result is the object that its operand points to. So, with *ptr++, the result is the object that ptr points to before the increment is applied.
Each expression if it is not a void expression has a value.
The value of the postfix increment is the value of its operand before incrementing.
From the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 The result of the postfix ++ operator is the value of the
operand. As a side effect, the value of the operand object is
incremented (that is, the value 1 of the appropriate type is added to
it)
That is this expression
*ptr++
is evaluated like
*( ptr++ )
and the value of the expression in the parentheses is the value of the pointer (the operand of the postfix increment) before incrementing of the operand itself that is evaluated as a side effect.
This is the difference between the postfix increment and the prefix increment for which (6.5.3.1 Prefix increment and decrement operators)
2 The value of the operand of the prefix ++ operator is incremented.
The result is the new value of the operand after incrementation.
It is useful to know that the postfix increment operator may be used to form a subscript expression while the prefix increment operator may not.
Here is a demonstrative program.
#include <stdio.h>
int main(void)
{
int a[] = { 1, 2 };
int *p = &a[0];
printf( "a[0] = %d, a[1] = %d\n", a[0], a[1] );
p++[0] = 3;
*p = 4;
printf( "a[0] = %d, a[1] = %d\n", a[0], a[1] );
return 0;
}
The program output is
a[0] = 1, a[1] = 2
a[0] = 3, a[1] = 4

What is '-1[p]' when p points to an array (of int) index? [duplicate]

This question already has answers here:
With arrays, why is it the case that a[5] == 5[a]?
(20 answers)
Closed 3 years ago.
Today I stumbled over a C riddle that got a new surprise for me.
I didn't think that -1[p] in the example below would compile, but it did. In fact, x ends up to be -3.
int x;
int array[] = {1, 2, 3};
int *p = &array[1];
x = -1[p];
I searched the internet for something like -1[pointer] but couldn't find anything. Okay, it is difficult to enter the correct search query, I admit. Who knows why -1[p] compiles and X becomes -3?
I'm the person that made this "riddle" (see my Twitter post)
So! What's up with -1[p]?
ISO C actually defines [] to be symmetrical, meaning x[y] is the same as y[x], where x and y are both expressions.
Naively, we could jump to the conclusion that -1[p] is therefore p[-1] and so x = 1,
However, -1 is actually the unary minus operator applied to the constant 1, and unary minus has a lower precedence than []
So, -1[p] is -(p[1]), which yields -3.
This can lead to funky looking snippets like this one, too:
sizeof(char)["abc"] /* yields 'b' */
First thing to figure out is the precedence. Namely [] has higher precedence than unary operators, so -1[p] is equal to -(1[p]), not (-1)[p]. So we're taking the result of 1[p] and negating it.
x[y] is equal to *(x+y), so 1[p] is equal to *(1+p), which is equal to *(p+1), which is equal to p[1].
So we're taking the element one after where p points, so the third element of array, i.e. 3, and then negating it, which gives us -3.
According to the C Standard (6.5.2 Postfix operators) the subscript operator is defined the following way
postfix-expression [ expression ]
So before the square brackets there shall be a postfix expression.
In this expression statement
x = -1[p];
there is used the postfix expression 1 (that is at the same time a primary expression), the postfix expression 1[p] (that is the subscript operator) and the unary operator - Take into account that when the compiler splits a program into tokens then integer constants are considered as tokens themselves without the minus. minus is a separate token.
So the statement can be rewritten like
x = -( 1[p] );
because a postfix expression has a higher priority than an unary expression.
Let's consider at first the postfix sub-expression 1[p]
According to the C Standard (6.5.2.1 Array subscripting)
2 A postfix expression followed by an expression in square brackets []
is a subscripted designation of an element of an array object. The
definition of the subscript operator [] is that E1[E2] is identical to
(*((E1)+(E2))). Because of the conversion rules that apply to the
binary + operator, if E1 is an array object (equivalently, a pointer
to the initial element of an array object) and E2 is an integer,
E1[E2] designates the E2-th element of E1 (counting from zero).
So this sub-expression evaluates like *( ( 1 ) + ( p ) ) and is the same as *( ( p ) + ( 1 ) ).
Thus the above statement
x = -1[p];
is equivalent to
x = -p[1];
and will yield -3, because the pointer p points to the second element of the array due to the statement
int *p = &array[1];
and then the expression p[1] yields the value of the element after the second element of the array. Then the unary operator - is applied.
This
int array[] = {1, 2, 3};
looks like
array[0] array[1] array[2]
--------------------------
| 1 | 2 | 3 |
--------------------------
0x100 0x104 0x108 <-- lets assume 0x100 is base address of array
array
Next when you do like
int *p = &array[1];
the integer pointer p points to address of array[1] i.e 0x104. It looks like
array[0] array[1] array[2]
--------------------------
| 1 | 2 | 3 |
--------------------------
0x100 0x104 0x108 <-- lets assume 0x100 is base address of array
|
p holds 0x104
And when you do like
x = -1[p]
-1[p] is equivalent to -(1[p]) i.e -(p[1]). it looks like
-(p[1]) ==> -(*(p + 1*4)) /* p holds points to array[1] i.e 0x104 */
==> -(*(0x104 + 4))
==> -(*(0x108)) ==> value at 0x108 is 3
==> prints -3
What happens here is really interesting.
p[n] means *(p+n). Thats why you see 3, because "p" points to array[1] which is 2, and -p[1] is interpreted as -(*(p+1)) which is -3.

differences in C: *source++, (*source)++, *(source)++

IS there a difference between these pointers? What exactly is happening here for each call.
*p++
(*p)++,
*(p)++
1 and 3 are the same.
Remember that both postfix and unary forms of ++ and -- have a result and a side effect:
The result of x++ is the current value of x - as a side effect, x is incremented by 1 (if x is a pointer, it is incremented to point to the next object in a sequence);
The result of ++x is the current value of x plus 1 - as a side effect, x is incremented by 1 (if x is a pointer, the result is the address of the next object in a sequence, and x is updated to point to the next object in a sequence);
Both forms of -- work the same way, except the value is decremented by 1 - if it's a pointer, then it's set to point to the previous object in a sequence.
When you throw pointer dereferences into the mix, you get the following:
The expression *p++ is parsed as *(p++) (so is *(p)++). The result of *p++ is the current value of *p (the value of the thing p is currently pointing to). As a side effect, p is incremented to point to the next object of the same type in a sequence (IOW, the next element of an array);
The expression (*p)++ is parsed as written. The result of (*p)++ is the current value of *p. As a side effect, *p is incremented by 1. That is, the value of the thing being pointed to is updated, not the pointer.
The expression ++*p is parsed as ++(*p). The result of ++*p is the current value of *p plus 1. As a side effect, *p is incremented by 1.
The expression *++p is parsed as *(++p). The result of *++p is the value of the object following the object p currently points to. As a side effect, p is incremented to point to the next object.
Assume the following declarations:
int a[] = {1, 2, 3, 4};
int *p = a;
After these lines, the value of p is &a[0]. So, given the expression
x = *p++;
the result of *p++ is 1 (the value of the thing p currently points to), which gets assigned to x. The side effect is that p is updated to point to a[1].
Then we execute
x = (*p)++;
The result of (*p)++ is the value of the thing p currently points to (if p points to a[1], then the value is 2), which gets assigned to x. As a side effect, the thing p points to is incremented (if p points to a[1], then the value of a[1] is now 3).
The we execute
x = ++*p;
The result of ++*p is the value of the thing p points to plus 1, and as a result the thing p points to is incremented (if p points to a[1], then the value of a[1] + 1 is 4, which is assigned to x, and the value of a[1] is now 4).
Finally, we execute
x = *++p;
The result of *++p is the value of the object following the object that p currently points to, and p is incremented to point to that object (if p points to a[1], then the value of a[2] (3) is written to x, and p is updated to point to a[2]).
Again, -- works the same way, just in the other direction.
tiny test program.
#include <stdio.h>
int main(void) {
char z[] = "World";
char n[] = "Something";
char *x = "Hello!!";
while(*x) printf("%c", *x++);
printf("\n");
x = z;
while(*x) printf("%c", (*x)++);
printf("\n");
x = n;
while(*x) printf("%c", *(x)++);
printf("\n");
return 0;
}
so the *x++ dereference the pointer, then increments the pointer
(*x)++ - only increments the referenced object.
*(x)++ == *x++
IMO instead of asking try yourself. You will learn something https://ideone.com/bliza0
*source++ will be parsed as *(source++) because of higher precedence of ++ over * operator. It will increment the pointer by 1 and then will dereference the pointer.
To understand the behaviour first let me explain how post increment operator works. When you do
int i = 0;
int j = i++;
then it means that the value of the expression i++ will be the value of the operand i. In this case it will be 0. The value of the i will be incremented as a side-effect. See the quote from the draft
n1570 - §6.5.2.4/2:
The result of the postfix ++ operator is the value of the operand. As a side effect, the value of the operand object is incremented (that is, the value 1 of the appropriate type is added to it). See the discussions of additive operators and compound assignment for information on constraints, types, and conversions and the effects of operations on pointers. The value computation of the result is sequenced before the side effect of updating the stored value of the operand.
In case of *source++, compiler will parse it as *(source++). The result of the expression source++ is the value of source. So the current pointer (the address source is pointing to before the side-effect) will be dereferenced and then the side-effect on source will be performed.
(*source)++ will first dereference the pointer and then increment the dereferenced value by 1.
*(source)++ is equivalent to the first case.
I apologies for the wrong answer and leaving the wrong answer with strikes so that future readers will take a lesson if any one come to the same wrong conclusion as I did. Thanks #interjay and #pmg for correcting me out. I am really glad that you guys are part of this community and contributing to this community with your sharp eyes and mind.

Operator precedence in C (pointer arithmetics) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
int* p = malloc(sizeof(int)*5);
*p = 1, *(p+1) = 2, *(p+2) = 3, *(p+3) = 4, *(p+4) = 5;
for(int i = 0; i < 5; i++){
//what exactly is going on in these lines?
printf("%d %p\n", (*p++)++, p);
//printf("%d %p\n", (*++p)++, p);
//printf("%d %p\n", ++(*p++), p);
//printf("%d %p\n", ++(*++p), p);
}
What is operator precedence in these lines above?
If we add parentheses to all potentially ambiguous expressions in the code above, we get:
int p = malloc((sizeof (int)) * 5);
(((((*p) = 1), ((*(p+1)) = 2)), ((*(p+2)) = 3)), ((*(p+3)) = 4)), ((*(p+4)) = 5);
for(int i = 0; i < 5; i++){
printf("%d %p\n", (*(p++))++, p);
}
That is:
sizeof has higher precedence than *
unary * has higher precedence than =, = has higher precedence than ,, and , is left associative
postfix ++ has higher precedence than unary *
There is no pointer arithmetic in your code because there are no pointers. int p declares an int.
That's why *p = 1 doesn't even compile, so this code doesn't actually do anything.
If you fix that, the code still doesn't do anything because the (*p++)++, p part in your printf call has undefined behavior: It's modifying p and reading from p without an intervening sequence point.
*p = 1, *(p+1) = 2, *(p+2) = 3, *(p+3) = 4, *(p+4) = 5;
is equivalent to (in that case, not always)
*p = 1; *(p+1) = 2; *(p+2) = 3; *(p+3) = 4; *(p+4) = 5;
concerning
printf("%d %p\n", (*p++)++, p);
the order of the execution or the arguments is indeterminate, so same for the result
P.S. next you put a code, please check before it is possible to compile it without error (int ptr = malloc(sizeof(int)*5); must be int * p = malloc(sizeof(int)*5);)
Let's draw some pictures. After the first two lines, you have the following:
+---+---+---+---+---+
| 1 | 2 | 3 | 4 | 5 |
+---+---+---+---+---+
^
|
|
|
+---+
p: | |
+---+
The expression (*p++)++ is parsed as (*(p++))++ and is evaluated as follows:
p++ - evaluate to the current value of p (&p[0]); as a side effect,
update `p` to point to the next object in the sequence (&p[1])
*p++ - dereference the result of `p++` (p[0])
(*p++)++ - evaluate to the current value of the thing `p` points to
(1), then increment the value of that thing.
After that expression has been evaluated, our state is now
+---+---+---+---+---+
| 2 | 2 | 3 | 4 | 5 |
+---+---+---+---+---+
^
|
+---+
|
+---+
p: | |
+---+
The expression (*++p)++ is parsed as (*(++p))++ and evaluates as:
++p - evaluate to the current value of p plus 1 (&p[2]), which gives us
the address of the next object in the sequence;
update p to point to the next object (&p[2])
*++p - dereference the result of ++p (p[2])
(*++p)++ - evaluate to the current value of thing following what p currently
points to (3), and as a side effect increment that thing.
After that expression has been evaluated, our state is now
+---+---+---+---+---+
| 2 | 2 | 4 | 4 | 5 |
+---+---+---+---+---+
^
|
+-------+
|
+---+
p: | |
+---+
You should be able to work out the other two. However...
The statement
printf("%d %p\n", (*p++)++, p);
invokes undefined behavior, because you're both trying to read p and update it without an intervening sequence point. The value that gets printed for p may or may not reflect the update from p++ or ++p. Function arguments are not guaranteed to be evaluated in any particular order.

What means *p++=x

I'm new in C and I'm wondering what *p++=x means.
I understand what var += x means, what *var++ means but I don't get this one.
It means assign x to *p and then make p point to the next element:
*p = x;
p++;
Postfix operators have higher precedence than unary operators, so *p++ is parsed as *(p++); that is, you are dereferencing the result of the expression p++.
So the expression *p++ = x assigns the value of x to whatever p is pointing to and advances p to point to the next element.

Resources