Okay, I know the output for the expression (x *= y = z = 4;) is 40; but how exactly did we get 40? Can you please show me step by step.
I thought the precedence is from right to left so (2 * 4) = (z =4), I don't understand
#include <stdio.h>
#define PRINTX printf("%d\n",x)
int main (void){
int x = 2, y, z;
x *= 3 + 2;
PRINTX;
x *= y = z = 4;
PRINTX;
x = y == z;
PRINTX;
x == ( y = z );
PRINTX;
return 0;
}
No, the only way that assignment can be evaluated here is right to left.
First, note that x *= 99, for example, is shorthand for x = x * 99.
With that said,
x *= y = z = 4;
is equivalent to
z = 4;
y = z;
x *= y; // This is shorthand for x = x * 4
Consider what would happen if you tried to evaluate it the other way around:
// y is unininitialized
x *= y;
y = z;
z = 4;
It would fail.
So really,
// x = 2
int x = 2, y, z;
// x = x * (3 + 2) = x * 5 = 2 * 5 = 10
x *= 3 + 2;
// x = x * 4 = 10 * 4 = 40
x *= y = z = 4;
This can be rewritten as
int x, y, z;
x = 2; // x = 2
x = x * (3 + 2); // This is 2 * 5, so x = 10 after this
z = 4; // z = 4
y = z; // y = 4
x = x * y; // x = 10 * 4 = 40
And that's how you end up with 40.
All of the assignment operators have equal precedence, and right-to-left associativity (which affects what happens when multiple operators of equal precedence are present in an expression).
This means x *= y = z = 4 is equivalent to x *= (y = (z = 4)). z = 4 must be evaluated first (which assigns z to 4, and gives a result of 4). The assignment y = ... then gives the value y the value of 4, and also produces a result of 4. The assignment x *= ... then multiples x (which has a value 10) by 4, giving a result of 40.
(The reason x *= 3 + 2 gives x the value 10 is that addition has higher precedence than assignment, so x *= 3+2 is equivalent to x *= (3 + 2) rather than (x *= 3) + 2.)
If the assignment operators were instead left-to-right associative, x *= y = z = 4 would be equivalent to (((x *= y) = y) = z) = 4 which would not compile.
You have:
int x = 2, y, z;
x *= 3 + 2;
This is a shorthand for x = x * (3 + 2), which evaluates to 10 given that x starts at 2.
PRINTX;
x *= y = z = 4;
After this, y == z and both are set to 4; and x is 4 times its previous value of 10, hence 40.
PRINTX;
x = y == z;
This compares y and z; they're equal, so x is assigned 1 (comparisons always evaluate to 0 or 1).
PRINTX;
x == ( y = z );
This assigns z to y (leaving the value unchanged at 4); nominally, this is compared with x but the compiler can ignore the comparison. Therefore, x is unchanged and still 1.
Related
I'm trying to code a mouse drag function in C. Basically, i want X to reach targetX, and Y to reach targetY at the same time. For example:
x = 0, y = 0;
targetX = 10, targetY = 20;
I want to make x reach targetX by the time y reaches targetY. I want it to loop until both x and y reach their target number, incrementing them by 1 each time to actually achieve that. So, at one point, x would be 9, and y would be 19, then it would increment them each by 1, causing them to both equal their target numbers, instead of x reaching targetX first, then y getting incremented solo (which is what my current code does). Also, i need it to be able to decrement (instead of increment) x or y (or both), as well.
Here is what i have now:
for (x; x < targetX || x > targetX;) {
x = (x < targetX) ? x + 1 : x - 1;
y = (y < targetY) ? y + 1 : y - 1;
mouse_move(x, y);
}
for (y; y < targetY || y > targetY;) {
y = (y < targetY) ? y + 1 : y - 1;
mouse_move(x, y);
}
It doesn't have to be in C, i'm just looking for a way to make x and y reach their target numbers at the same time.
Save the initial x.
Save the initial y.
delta x = target x - initial x
delta y = target y - initial y
num steps = max of the deltas (or whatever you want)
For step = 1 .. num steps,
fraction = step / num steps
x = initial x + ( fraction * delta x )
y = initial y + ( fraction * delta y )
Move the mouse
I am pretty sure I got this right just want to make sure though... In the following code, we have omitted the definitions of constants M and N
here are the two functions in question arith and optarith:
#define M /* Mystery number 1 */
#define N /* Mystery number 2 */
unsigned int arith(unsigned int x, unsigned int y){
unsigned int result = 0;
result = x * M + y/N;
return result;
}
We compiled this code for particular values of M and N. The compiler optimized the multiplication and
division. The following is a translation of the generated machine code back into C:
unsigned int optarith(unsigned int x, unsigned int y){
unsigned int t = 3 * x;
x <<= 6;
x -= 2 * t;
y >>= 4;
y = y/3;
return x + y;
}
so here's my work
so to find value M for the operation M * x
x <<= 6; // same as x = x * 64
x-= 2 * t; //same as x = x - 2 * (3 * x)
so basically x = 64x - 6x which is just 58x therefore M = 58
and to find the value N for operation y/N
y >>= 4; same as y = y/16;
y = y/3; same as y = (y/16)/3;
that makes y/48 so N = 48
Did I do this correctly?
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 7 years ago.
Improve this question
Can anyone explain to me how this code is being calculated using operators.
#include <stdio.h>
int main(void)
{
int x = 2, y , z;
x *= 3;
printf("%d\n", x);
x = x * (3 + 2);
printf("%d\n", x);
x *= y = z = 4;
printf("%d\n", x);
x *= y += z;
printf("%d %d %d\n", x, y, z);
return 0;
}
As a result, I got the following output:
6,
30,
120,
960, 8, 4,
The operator followed by an equal sign means that the operator is applied to the variable on the left and the variable on the right, followed by an assignment to the variable on the left. You also follow the precedence operations. I have expanded the meaning below.
x *= 3;
is the same as
x = x * 3; // 6 = 2*3
The parentheses shows order of precedence
x = x * (3+2) // x was 6 from the previous line
this is
x = x * 5 // which gives 30
next
x *= y = z = 4;
means
z = 4;
y = z; //which is 4
x = x *y; // which is 120 = 30 *4
next
x *= y += z;
means
y = y + z ; // y = 4 + 4 (8)
x = x * y; // x = 120 * 8 (960)
*= multiplies left operand by right operand and assigns result to left.
x *= y = z = 4;
Works right to left, assigning 4 to z and y then multiplying x by 4.
x *= y += z;
z is added to y and result is assigned to y, then x is multiplied by y and result is assigned to x.
x*=3 means x=x*3 => x=2*3=6
x*=(3+2) means x=x*(3+2) => x=6*5=30
x*=y=z=4 means z=4, then y=4, then x=x*y => x=30*4=120
x*=y+=z means y=y+z then x=x*y => y=4+4=8 then x=120*8=960.
The first two assignments are straightforward: multiplying x by 3 gives you 6, and then by (3+2) gives you 30.
The third assignment features a chain of assignments, with 4 assigned to y and z. Since the value of an assignment is always the value of its left side after the assignment, the final multiplication x *= y multiplies x by 4, giving you 120.
The last line is the trickiest, because it features two side effects. First, y += z is evaluated, producing 8. After that x is multiplied by 8, producing its final value of 960.
Note that in the last line x is multiplied by 8, which may or may not be the value of y at the time the multiplication is performed.
So I'm wondering, how do I make sure that all steps in a loop are performed if the step size is smaller than 1? Take this loop for instance:
for (float y, x = -1.0; x <= 1.0; x += 0.1) {
y = (4*x*x*x) + (3*x*x) + (5*x) - 10;
printf("x = %.2f, y = %.2f\n", x, y);
}
Output:
x = -1.00, y = -16.00
x = -0.90, y = -14.99
x = -0.80, y = -14.13
x = -0.70, y = -13.40
x = -0.60, y = -12.78
x = -0.50, y = -12.25
x = -0.40, y = -11.78
x = -0.30, y = -11.34
x = -0.20, y = -10.91
x = -0.10, y = -10.47
x = 0.00, y = -10.00
x = 0.10, y = -9.47
x = 0.20, y = -8.85
x = 0.30, y = -8.12
x = 0.40, y = -7.26
x = 0.50, y = -6.25
x = 0.60, y = -5.06
x = 0.70, y = -3.66
x = 0.80, y = -2.03
x = 0.90, y = -0.15
I intend the loop to also run for x = 1, but as you can see it doesn't do that. I've heard that it's not safe to use floats as loop counters, as the float precision isn't exact. The fact that I'm using a float variable as the loop counter is probably the cause of my problem. So what solutions are there to my problem? Thanks in advance for your kind responses!
The problem, as you noted, is that you shouldn't use floats as loop counters. So multiply everything by 10 and use integers:
for (int x = -10; x <= 10; ++x) {
float y = (0.004*x*x*x) + (0.03*x*x) + (0.5*x) - 10;
printf("x = %.2f, y = %.2f\n", 0.1*x, y);
}
Produces:
x = -1.00, y = -16.00
x = -0.90, y = -14.99
x = -0.80, y = -14.13
...
x = 0.90, y = -0.15
x = 1.00, y = 2.00
as expected.
Perhaps even better: logically separate your loop variable from the meaningful stuff.
for(int i = -10; i <= 10; ++i) {
float x = 0.1 * i;
float y = (4*x*x*x) + (3*x*x) + (5*x) - 10;
printf("x = %.2f, y = %.2f\n", x, y);
}
Is this code:
y = x = x + 1;
undefined behavior in C?
Answer to your question
No.
What will happen
This will happen:
int x = 1; /* ASSUME THIS IS SO */
y = x = x + 1;
/* Results: */
y == 2;
x == 2;
How it compiles
The same as:
x += 1;
y = x;
Why this is not undefined
Because you are not writing x in the same expression you read it. You just set it to itself + 1, then assign y to the value of x.
Your future
If you find the code confusing you can use parentheses for readability:
y = x = (x + 1);
No, your expression is properly defined. You probably were looking for y = x = x++;, which is not.
No. You only modify x once, and due to the right-associativity of = that assignment happens before the assignment to y. Even if it did happen after, there's still only one modification of x. Your statement is as legal as y = ++x.