difference between *y++ and ++*y? - c

I'm confused in how this code will get executed. Suppose we have
int x=30,*y,*z;
y=&x;
what is the difference between *y++ and ++*y? and also what will be the output of this program?
#include<stdio.h>
int main(){
int x=30,*y,*z;
y=&x;
z=y;
*y++=*z++;
x++;
printf("%d %d %d ",x,y,z);
return 0;
}

The expression x = *y++ is in effects same as:
x = *y;
y = y + 1;
And if expression is just *y++; (without assignment) then its nothing but same as y++;, that is y start pointing to next location after increment.
Second expression ++*y means to increment the value pointed by y that same as: *y = *y + 1; (pointer not incremented)
It will be better clear with answer to your first question:
Suppose your code is:
int x = 30, *y;
int temp;
y = &x;
temp = *y++; //this is same as: temp = *y; y = y + 1;
First *y will be assigned to temp variable; hence temp assigned 30, then value of y increments by one and it start point to next location after location of x (where really no variable is present).
Next case: Suppose your code is:
int x = 30, *y;
int temp;
y = &x;
temp = ++*y; //this is same as *y = *y + 1; temp = *y;
First value of *y increments from 30 to 31 and then 31 is assigned to temp (note: x is now 31).
next part of your question (read comments):
int x = 30, *y, *z;
y = &x; // y ---> x , y points to x
z = y; // z ---> x , z points to x
*y++ = *z++; // *y = *z, y++, z++ , that is
// x = x, y++, z++
x++; // increment x to 31

what is the difference between *y++ and ++*y?
The meaning of an expression in C is characterized by two things: what value it produces and what side effects it produces.
Let's examine the first expression.
Postfix increment is of higher priority than dereferencing, so this is *(y++).
The postfix increment produces a side effect: it changes the value of y to point to a different location. The postfix increment also produces a value: the value that y had before it was incremented. The * operator then dereferences that value to produce an lvalue: that is, something you can use as a variable, either to store to or to fetch from.
I note that the side effect can happen at any point before or after the dereferencing. If you said
q = *y++
then the side effect of the ++ could happen at any point. This could be:
q = *y;
y = y + 1;
or it could be treated as
t = y;
y = y + 1;
q = *t;
Both are perfectly legal. (Except of course that if y is itself an expression with side effects, those side effects must be produced only once. For clarity, I'll make that assumption throughout.)
How about ++*y? That is straightforward: *y produces a variable, the content of the variable is incremented, and the value of the expression is the incremented value. Note that again, the side effect can be produced out-of-order:
q = ++*y
could be treated as:
t = *y + 1;
*y = t;
q = t;
or as
t = *y + 1;
q = t;
*y = t;
Remember, C does not produce very many restrictions on the order in which side effects may happen, so be careful.

what is the difference between *y++ and ++*y?
In case of expression *y++ and *z++; because the postfix version ++ takes precedence over *, the compiler sees this as;
*(y++) = *(z++);
In case of ++*y; compiler sees this as ++(*p) and it will first increment the value of the object it points to ( x in this case) and then return its incremented value.
Summary table for other possibilities;
Expression Meaning
-------------------------------------------------------------------------------------
*y++ or *(y++) Value of expression is *y before increment; increment y latter
(*y)++ Value of expression is *y before increment; increment *t later
*++y or *(++y) Increment y first; value of expression is *y after increment
++*y or ++(*y) Increment *y first; value of expression is *y after increment
EDIT: As pointed out by Eric Lippert in his comment that saying: value of expression is *y before increment, increment y later is misleading, I want to clarify here that the words I used latter and after to emphasize that previous or next value of *y, respectively, will be used in expressions.
Note that, the side-effect can be produced in any order, either side-effect produce first and value assigned latter or value assigned first and side-effect produce latter. For more detail read the answers :-- 1, 2 given by Eric Lippert.

I trust that you understand what the operators ++ and * means when used separately. When used together then operator precedence comes into play. In C++ the ++ operator has a higher precedence than the * operator. So effectively *y++ means *(y++) and ++y* means (++y)*. I hope this helps.

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.

Precedence in C operators == and ( = )

I have to analyze what some code in C does, and I have a doubt about what happens in a certain line. The code is
#define PRINTX printf("%d\n", x)
void problem() {
int x = 2, y, z;
x *= 3 + 2; PRINTX;
x *= y = z = 4; PRINTX;
x = y == z; PRINTX;
x == (y = z); PRINTX; // This line is the problem
}
This code snippet prints the resulting numbers:
10
40
1
1 // This result **
the problem is that I'm still trying to figure out why does the last line prints out x = 1, when the operation is x == (y = z). I'm having trouble finding out what that 1 means and the precedence of the operations. Hope someone can help me! :)
Nothing in the last statement changes the value of x, so its value remains unchanged.
Parens were used to override precedence, forcing the = to be the operand of the ==.
An operator's operands must necessarily be evaluated before the operator itself, so we know the following:
y is evaluated at some point before the =.
z is evaluated at some point before the =.
x is evaluated at some point before the ==.
= is evaluated at some point before ==.
That's it. All of these are valid orders:
z y = x ==
y z = x ==
x y z = ==
etc.
But whenever x, y and z are evaluated, we can count on the following happening:
= assigns the value of z (currently 4) to y and returns it.
== compares the value of x (currently 1) with the value returned by = (4). Since they're different, == returns 0 (which isn't used by anything).
As you see, nothing changed x, so it still has the value it previously had (1).
In the last statement, nothing is changing the value of x. We are testing if x equals something, but we aren't changing it's value.
So it continues having the same value as it had in the previous statement, in particular, a value of 1.
the reason is because the == operator checks if the 2 numbers are equal, and returns 1 if equal and 0 if not equal that is why it returns one you can check by making x= 1 and y=2 and using the == operator between them
The comparison result of x and assignment of y with (y = z) is discarded. Last line could have dropped the compare: y = z; PRINTX;.
The assignment is not subsequently used either, so the line could have been PRINTX;.

C multiple variable assignment

I'm first year student in Software Engineering and in my last task I used (chain assignment) multiple assignment of values.
The lecturer claims that it is illegal to assign values in this way.
X = Y = Z;
(The three variables are declared in the beginning of the function).
I would be happy if you can explain to me if the assign is right action and if what the teacher claims is right.
It depends on whether all of the objects were correctly declared and Z was initialized or assigned with an appropriate value before this statement or not.
You can even assign values of objects of different types due to implicit casting, but the object which is getting assigned needs to be capable of holding the value of the object which is assigned to this one.
If Z was initialized or assigned before and all objects were correct declared, then:
X = Y = Z;
is completely correct and legal as it assigns the value held in Z to Y and X - the assignment takes place from right to left.
For example:
int X,Y,Z; // All objects are declared.
Z = 24; // `Z` is assigned with the integer value 24.
X = Y = Z; // `X` and `Y` get assigned by 24 which is the value in `Z`.
Else if Z has an indeterminate value (f.e. if it was not declared with the extern or static keyword or declared at global scope) and you would assign this value to Y and X with that statement.
Although the assignment itself would be even then not illegal, if you would use one of the assigned objects the program would give undefined results/output.
Speaking for the multiple assignments only, there is nothing illegal about it, you could even use:
O = P = Q = R = S = T = U = V = W = X = Y = Z;
if all objects used were correctly declared before and Z has an determined value.
The lecturer claims that it is illegal to assign values in this way.
If it is possible, I would ask her/him or your teacher, what s/he meant with that. Maybe there is something specific to your course you should care about.
Almost every expression has a value.
An assignment is an expression with value.
The value of the expression i = 42 is 42.
Assignment associates right to left, so the expression a = b = c is the same as a = (b = c).
So
int i;
double d;
char c;
c = i = d = 42;
Converts 42 to double and assigns to d. The value of this assignment is 42.0.
Then this value is converted to int and assigned to i. Value of this assignment is 42.
Lastly the int value is converted to char and assigned to c.
c = (i = (d = 42));
It's legal, for example:
float x;
int y;
float z = 3.5;
x = y = z;
it's similar to y = z; x = y;. So in this case, z = 3.5, y = 3 and x = 3;
But it will give the warning if you did not initialize the value of z.
int x,y, z;
x = 0;
y = 1;
//z = 2;
x = y = z;
Together with right-associativity of evaluation, and assuming non-volatile a, b, and c, it means that a = b = c is equivalent to a = (b = c), and again equivalent to b = c; a = b
Assigning values to multiple variables in a single line is perfectly alright and is allowed by C programming language.
However, the use of this style is usually discouraged because it may cause undesirable side-effects in some cases.
The expectation of Mathematical equation X = Y = Z may be:
Y = Z and X = Z (I.E., Assign the value of Z to both X and Y)
But C language treats the multiple assignments like a chain, like this:
In C, "X = Y = Z" means that the value of Z must be first assigned to Y, and then the value of Y must be assigned to X.
Here is a sample program to see how the multiple assignments in single line work:
#include <stdio.h>
int main() {
int n;
int X, Y, Z;
printf("Enter an integer: ");
scanf("%d", &n);
printf("You entered: %d\n", n);
printf("Performing multiple assignments:\n X = Y = Z = n++ \n");
X = Y = Z = n++;
printf("n = %d\n", n);
printf("X = %d \n", X);
printf("Y = %d \n", Y);
printf("Z = %d \n", Z);
return 0;
}
Output:
Enter an integer: 100
You entered: 100
Performing multiple assignments:
X = Y = Z = n++
n = 101
X = 100
Y = 100
Z = 100
Points to note in the above example:
The line X = Y = Z = n++ got processed like this:
Step 1: Assign the value of n (100) to Z
Step 2: Increment the value of n (n becomes 101)
Step 3: Assign the value of Z to Y (Y becomes 100)
Step 4: Assign the value of Y to X (X becomes 100)
Conclusion:
'Multiple assignments in single line' is a supported style. It has its benefits.
However, if the programmer is not aware of the sequence of operations involved in the multiple assignments statement, then it can lead to inconsistency between the expectation of the person who reads the program and the actual result of the execution.
To avoid this scenario, the multiple assignments are discouraged.
There's nothing illegal about it, provided each variable is only modified once. For example, the following all have well-defined behavior:
x = y = z;
x = y = z = x + 1;
x = y++ + --z;
x += (y = (z += 1)) - 6;
But the following have undefined behavior, and should be avoided:
x = y = x = z;
x = x++;
x = y++ + y++
x = func(y++, y++);

Post increment and Pre increment in C

I have a question about these two C statements:
x = y++;
t = *ptr++;
With statement 1, the initial value of y is copied into x then y is incremented.
With statement 2, We look into the value pointed at by *ptr, putting that into variable t, then sometime later increment ptr.
For statement 1, the suffix increment operator has higher precedence than the assignment operator. So shouldn't y be incremented first and then x is assigned to the incremented value of y?
I'm not understanding operator precedence in these situations.
You're mistaken about the meaning of your 2]. Post-increment always yields the value from before the increment, then sometime afterward increments the value.
Therefore, t = *ptr++ is essentially equivalent to:
t = *ptr;
ptr = ptr + 1;
The same applies with your 1] -- the value yielded from y++ is the value of y before the increment. Precedence doesn't change that -- regardless of how much higher or lower the precedence of other operators in the expression, the value it yields will always be the value from before the increment, and the increment will be done sometime afterwards.
Difference between pre-increment and post-increment in C:
Pre-increment and Post-increment are built-in Unary Operators. Unary means: "A function with ONE input". "Operator" means: "a modification is done to the variable".
The increment (++) and decrement (--) builtin Unary operators modify the variable that they are attached to. If you tried to use these Unary Operators against a constant or a literal, you will get an error.
In C, here is a list of all the Built-in Unary operators:
Increment: ++x, x++
Decrement: −−x, x−−
Address: &x
Indirection: *x
Positive: +x
Negative: −x
Ones_complement: ~x
Logical_negation: !x
Sizeof: sizeof x, sizeof(type-name)
Cast: (type-name) cast-expression
These builtin operators are functions in disguise that take the variable input and place the result of the calculation back out into the same variable.
Example of post-increment:
int x = 0; //variable x receives the value 0.
int y = 5; //variable y receives the value 5
x = y++; //variable x receives the value of y which is 5, then y
//is incremented to 6.
//Now x has the value 5 and y has the value 6.
//the ++ to the right of the variable means do the increment after the statement
Example of pre-increment:
int x = 0; //variable x receives the value 0.
int y = 5; //variable y receives the value 5
x = ++y; //variable y is incremented to 6, then variable x receives
//the value of y which is 6.
//Now x has the value 6 and y has the value 6.
//the ++ to the left of the variable means do the increment before the statement
Example of post-decrement:
int x = 0; //variable x receives the value 0.
int y = 5; //variable y receives the value 5
x = y--; //variable x receives the value of y which is 5, then y
//is decremented to 4.
//Now x has the value 5 and y has the value 4.
//the -- to the right of the variable means do the decrement after the statement
Example of pre-decrement:
int x = 0; //variable x receives the value 0.
int y = 5; //variable y receives the value 5
x = --y; //variable y is decremented to 4, then variable x receives
//the value of y which is 4.
//x has the value 4 and y has the value 4.
//the -- to the right of the variable means do the decrement before the statement
int rm=10,vivek=10;
printf("the preincrement value rm++=%d\n",++rmv);//the value is 11
printf("the postincrement value vivek++=%d",vivek++);//the value is 10

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).

Resources