What means *p++=x - c

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.

Related

Why do the following C expressions involving pointers not evaluate to an error?

I have been reviewing material regarding C for the upcoming semester, and stumbled across some topics involving pointers and memory. I did not write the code, but I am trying to understand all of it. The expressions are as follows (for conciseness I removed int main()):
int x = 5;
int y;
int *p = NULL;
p = &x;
y = *p + 2; /* y is assigned 7 */
y += *p; /* y is assigned 12 */
*p = y; /* x is assigned 12 */
(*p)++; /* x is incremented to 13 */
I do not understand the 7th statement, because it isn't consistent with the way the 5th statement is evaluated. As far as I was concerned, *p is used to access the value p points to, being x, which is 5. In the 5th statement, we set y = *p + 2, which evaluates to y = 5 + 2 = 7. So, why in the 7th statement is *p used as a pointer to x, and not the value 5? (ie. why doesn't the expression evaluate to 5 = 12 and give an error?).
Thanks for any of the help, appreciate it.
*p = y; sets *p to the value of y and does not set 5 to the value of y for the same reason that x = y; sets x to the value of y and does not set 5 to the value of y.
Specifically, in most places, when there is expression that refers to an object, like x or *p or y, it is automatically converted to the value stored in that object. This is why, in x = y;, the y is converted to 12. This conversion occurs due to C 2018 6.3.2.1, which says:
… an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue)…
But the full sentence lists exceptions:
Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue)…
In x = y; or *p = y;, the x or *p is the left operand of an assignment operator. So these are not converted to values. Each remains an lvalue. An lvalue is a reference to an object; it designates the object itself, not its value.
So x = y; puts the value of y into the object referred to by x, and *p = y; puts the value of y into the object referred to by *p.
why doesn't the expression evaluate to 5 = 12
It's possible to write to the memory pointed to by a pointer.
Similarly, x = y; is valid because you can read from the variable y and you can write to x. Same thing with pointers: *p = *p + 1;, for example, will read from p, add one to that value and write the result back to p.

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

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.

pre/post increment pointer

Is there a difference between the two expressions:
(*x)++
and
++(*x)
I can see both of these statements replace the contents of (*x+1) in *x. But are there any differences between them?
(*x)++ evaluates to the value of*x; as a side effect, the value in *x will be incremented by 1.
++(*x) evaluates to the value of *x + 1; as a side effect, the value in *x will be incremented by 1.
Assuming the code:
int a = 5;
int *x = &a;
(*x)++ will evaluate to 5, while ++(*x) will evaluate to 6.
Note that the side effect does not have to be applied immediately after the expression has been evaluated; it only needs to be applied before the next sequence point.
Also note that the parentheses matter for (*x)++; postfix ++ has higher precedence than unary *, so *x++ would be parsed as *(x++); it still evaluates to the value of *x, but as a side effect advances the pointer, rather than increment the thing being pointed to. Prefix ++ and unary * have the same precedence, so they're applied left-to-right; thus ++(*x) and ++*x would have the same result (*x gets incremented, not x).
Let us say the value pointed by x is 10 i:e (*x is 10)
y = (*x)++;
the above statement will be executed as
1. y = *x
2. *x = *x + 1
so y = 10 & *x is 11
y = ++(*x);
the above statement will be executed as
1. *x = *x + 1
2. y = *x
so y = 11 & *x is 11
One increments the values stored in x before it is used (pre), while the other does it after it is used (post).
Also note that ++(*x) is not the same as (*x + 1). The first increments the value and stores it back, the other just increments the value.
One is "pre" and the other is "post". That's the difference. One is evaluated before the the increment (the first option), the other is evaluated after the increment (the second option).

Post-increment in a while loop

The following code confused me a bit:
char * strcpy(char * p, const char * q) {
while (*p++=*q++);
//return
}
This is a stripped down implementation of strcpy function. From this code, we see that pointer p and q are incremented then dereferenced and q is assigned to p until the \0 char has been reached.
I would like someone to explain the first iteration of the while loop.
Because the ++ is after the variables, they aren't incremented until after the expression is evaluated. That's why it's the post-increment operator; the pre-increment is prefixed (++p). *++p would write to the second spot, *p++ writes to the first.
No, the increment happens after the assignment.
If it were *(++p), the pointer p would be incremented and after that assigned.
p++ is post-incrementing the pointer p. So the current value of p is operated upon by the deference operator * before p is incremented.
Your reasoning would've been correct if the while loop was written as follows:
while (*++p=*++q);
In this case the increment would happen before dereferencing.
The expressions x++ and ++x have both a result (value) and a side effect.
The result of the expression x++ is the current value of x. The side effect is that the contents of x are incremented by 1.
The result of the expression ++x is the current value of x plus 1. The side effect is the same as above.
Note that the side effect doesn't have to be applied immediately after the expression is evaluated; it only has to be applied before the next sequence point. For example, given the code
x = 1;
y = 2;
z = ++x + y++;
there's no guarantee that the contents of x will be modified before the expression y++ is evaluated, or even before the result of ++x + y++ is assigned to z (neither the = nor + operators introduce a sequence point). The expression ++x evaluates to 2, but it's possible that the variable x may not contain the value 2 until after z has been assigned.
It's important to remember that the behavior of expressions like x++ + x++ is explicitly undefined by the language standard; there's no (good) way to predict what the result of the expression will be, or what value x will contain after it's been evaluated.
Postfix operators have a higher precedence than unary operators, so expressions like *p++ are parsed as *(p++) (i.e., you're applying the * operator to the result of the expression p++). Again, the result of the expression p++ is the current value of p, so while (*p++=*q++); doesn't skip the first element.
Note that the operand to the autoincrement/decrement operators must be an lvalue (essentially, an expression that refers to a memory location such that the memory can be read or modified). The result of the expression x++ or ++x is not an lvalue, so you can't write things like ++x++ or (x++)++ or ++(++x). You could write something like ++(*p++) (p++ is not an lvalue, but *p++ is), although that would probably get you slapped by anyone reading your code.
The right hand side of the expression (*q++) will be evaluated prior to *p++, and both will only be incremented after the assignment takes place.
Read the statement right to left and remember post-increment (q++ instead of ++q) happens after everything else in the line is resolved.
*q --> dereference q
= --> assign the value
*p --> to p
increment both.
Do this until q p taking q's element = 0 which is when it reaches the null terminator.
The value of q++ is q
The value of ++q is q+1
This is a stripped implementation of strcpy function. From this code, we see that pointer p and q are increamented, than dereferenced and q is assigned to p until \0 char has been reached.
It happens the other way around. The value at *p is set to *q, then both pointers are incremented.
When you have int foo = bar++ the increment happens after foo has been set. To have it happen first you would do int foo = ++bar
The while loop's condition is performing post-increment. Equivalently:
while (true) {
char* old_p = p;
const char* old_q = q;
++p; // or p++;
++q; // or q++;
*old_p = *old_q;
if (*old_p == '\0')
break;
}

Resources