Is `y = x = x + 1;` undefined behavior? - c

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.

Related

Solving compound assignment expressions

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.

Calculating numbers with operators [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 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.

Calculate the number of all possible execution paths in a C function

I am desperately looking for a way to easily calculate the number of all possible execution paths in a C function.
For example, for the following function I would expect to get a result of 3 (if there is a chance based on the values that 'i' gets to enter any of the 'if' statements)
void test(void)
{
if (i>0)
x = x + 1;
else if (i>10)
x = x + 2;
else
x = x + 3;
}
Use comma operator as
int test(void)
{
int ways = 0;
if (++ways, i>0)
x = x + 1;
else if (++ways, i>10)
x = x + 2;
else
{
x = x + 3;
++ways;
}
return ways;
}

Trying to get this for loop to work?

I just started to learn C so the answer is probably incredibly obvious but when I run this code the number 0 just keeps repeating in an infinite loop. I'm trying to print x from 0 to 1 in increments of .05.
#include <stdio.h>
int main()
{
double x;
for( x = 0; x <= 1; x+.05 )
{
printf("%d\n", x );
}
}
for( x = 0; x <= 1; x += .05 )
seems like your not writing the changed x value to x..... If you know what I mean :D
x++ is the same as x+=1
x+.05 doesn't modify x's value, thus x will always be 0 and result in a infinite loop...
I think that's what you're looking for:
for( x = 0; x <= 1; x+=0.05 )
{
printf("%f\n", x );
}
You'll want to change to the += sign and change the d to an f.
d is for decimal integers
f is for floating point numbers
You want the addition and assignment compound operator, which is +=, not just +.
for( x = 0; x <= 1; x+=.05 )
Currently the result of your expression is x + 5, and its result is not used, resulting in your loop's condition never being false.
Change the line in your for loop to
for( x = 0; x <= 1; x += .05 )
Note that
x += .05
Is equivalent to typing
x = x + .05
which is what you really want since the goal is to update the value of x.

Valid to use assignment operator in C expression?

Instead of
cardNumber = j+1;
deck[i][j] = cardNumber;
theDeck[k] = cardNumber;
is it valid to just say
deck[i][j] = theDeck[k] = cardNumber;
to assign cardNumber to both deck and theDeck at the same time??
Yes, it is. The assignment operator returns a value.
Yes, it's an expression and its value is the right side of the assignment. Note that this comes also from the associativity of = (right-to-left), which makes this:
x = y = z
Equivalent to:
x = (y = z)
But not:
(x = y) = z /* wouldn't work */
So you can go even further and write:
theDeck[k] = deck[i][j] = cardNumber = j+1;
Yes it is; it is like this:
deck[i][j] = (theDeck[k] = cardNumber);

Resources