Where would the associativity of the = assignment operator make a difference in an expression? I thought that the associativity relates to operands that share an operator, but in the case of assignment, how would that work? A few examples that (might) be relevant are:
x = 1
x + 2 = y + 3 = z + 5
Does this just mean that, in the assignments above, we would have:
y + 3 = z + 5
Done before, for example:
x + 2 = y + 3
Or what other scenarios are there where assignment associativity 'matters' ?
Your examples don't demonstrate anything, because associativity only comes into play when you have several operators with the same precedence (or the same operator) next to each other.
Consider x = y = 42, which sets both variables to 42.
Because of right-associativity, it's parsed as x = (y = 42), where y = ... returns the new value of y, which is 42.
This is why it works. If = was left-associative and it was parsed as (x = y) = 42, then:
In C it wouldn't compile at all, because x = ... returns an rvalue rather than an lvalue, and those can't be assigned to.
In C++, where assignments return lvalues, it would work like x = y; x = 42;, which is far from being intuitive.
Related
given that
int w = 1;
int x = 6;
int y = 5;
int z = 0;
z = !z || !x && !y;
printf("%d\n", z);
z = x-- == y + 1;
printf("%d\n", z);
Could someone explain how the line below would evaluate to 1 if x-- is 5 and y+1 is 6?
z = x-- == y + 1;
The expression x-- evaluated to the value of x before being decremented.
So x-- == y + 1 is the same as 6 == 5 + 1 which is true, then the value 1 is assigned to z.
The expression
z = x-- == y + 1
will be parsed as
z = ((x--) == (y + 1))
IOW, you are comparing the result of x-- to the result of y + 1, and assigning the result of that comparison to z.
The result of x-- is the current value of x; the side effect is that x is decremented. So, given
x == 6
y == 5
then
x-- == 6
y + 1 == 6
(x-- == y + 1) == 1
so 1 is assigned to z; after this evaluation, x will equal 5.
Note that C does not force left-to-right evaluation in this case - y + 1 may be evaluated before x--. Also be aware that the side effect of the -- operator on x does not have to be applied immediately after evaluation - the whole thing could be evaluated as
t1 <- y + 1
t2 <- x
z <- t2 == t1
x <- x - 1
or
t1 <- x
t2 <- y + 1
x <- x - 1
z <- t1 == t2
or any other order. The update to x and the assignment to z can happen in any order, even simultaneously (either interleaved or in parallel).
While idiomatic C is often a little head-scratchy, this takes things a bit too far. As an academic exercise for learning about operator precedence and side effects it's okay (not great), but anyone who did this in production code could expect some grief over it in a code review. If nothing else it doesn't scan well - just adding some parens (like I did above) would greatly help with readability.
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).
3 The postfix -- operator is analogous to the postfix ++ operator,
except that the value of the operand is decremented (that is, the
value 1 of the appropriate type is subtracted from it)
Thus in this expression statement
z = x-- == y + 1;
that may be equivalently rewritten like
z = ( x-- ) == ( y + 1 );
the value of the postfix decrement expression x-- is the value of the variable x before decrementing. That is the value of the expression is equal to 6.
The value of the expression y + 1 is also equal to 6 because the value of y is equal to 5.
And at last (the C Standard, 6.5.9 Equality operators)
3 The == (equal to) and != (not equal to) operators are analogous to
the relational operators except for their lower precedence.108) Each
of the operators yields 1 if the specified relation is true and 0 if
it is false. The result has type int. For any pair of operands,
exactly one of the relations is true
So as the value of the expression x-- is equal to the value of the expression y + 1 then the variable z gets the value 1.
You could get the expected by you result keeping the postfix decrement operator the following way
z = ( x--, x == y + 1 );
by inserting the comma operator. In this case after the comma operator there is a sequence point that means that in second operand of the comma operator x == y + 1 x will be already equal to 5.
On the other hand, if you will write for example the expression like this
z = --x == y + 1;
where instead of the postfix decrement operator there is used unary decrement operator -- then the value of the expression --x will be equal to 5 (the value of the unary decrement operator is the value of its operand after decrementing). In this case the variable z gets the value 0 because 5 is not equal to 6 (the value of the expression y + 1).
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;.
When i compile this code,it showing an error as lvalue required as increment operand
int main(void)
{
int x,y,z;
x=8++;
y=++x++;
z=(x+y)--;
printf("x=%d,y=%d,z=%d",x,y,z;
return 0;
}
When you write something++ or ++something it's roughly equivalent to
something = something + 1
(the difference between something++ and ++something is in what you get when you assign the result to something else).
Because of this, the operand of ++ has to be something you can assign to.
8++ is equivalent to 8 = 8 + 1, but you can't assign to a number.
++x++ would be equivalent to something like (x = x + 1) = (x = x + 1) + 1, I can't even fathom what this could be intended to mean.
(x+y)-- is equivalent to (x + y) = (x + y) - 1. You can't assign to an addition expression (which variable would you be setting)?
You should only use ++ or -- when you actually want to update a variable. It's not a general replacement for + 1 or - 1. So your program should be:
x = 8 + 1;
y = 1 + x + 1;
z = (x + y) - 1;
This will print
x = 9, y = 11, z = 19
constant cannot be changed. 8 is a constant value. (x+y) is also not the value which can be incremented and stored somewhere.
x++ uses the value of x then increments the x. So the lvalue is changed itself not only the result of the operation.
correct is
z=(x+y)-1;
x=8+1;
I have a problem understanding the output of the code. Any explanation please...
#include<stdio.h>
void main()
{
int x=2,y=5;
x*=y+1;
printf("%d",x);
}
The output is as 12. But as per my understanding x*=y+1;is x=x*y+1; but as per operator precedence x*y should be evaluated followed by adding 1 so it should be 10+1=11. But it is 12 — can anyone explain please?
It will be evaluated as
x = x * (y + 1);
so
x = 2 * ( 5 + 1 )
x = 12
What's going on here is how the order of operations happens in programming.
Yes, if you were to have this equation x*y+1 it would be (x * y ) + 1 and result in eleven.
But in programming, the equation to the right of the = sign is solved for prior to being modified by the symbol proceeding the = sign. In this equation it is multiplied.
So x *= y + 1 is actually x = x * ( y + 1 ) which would be 12.
^ In this case, the asterisk(*) is multiplying the entire equation on the right hand side by x and then assigning that outcome to x.
It is translated into : x = x*(y+1);
So very obviously it prints out 12.
Your understanding is correct but it's somthing like this:
x*=y+1; => x = x * (y + 1);
Now apply BODMAS
x *= y + 1 is x = x * (y + 1)
Operator + has higher precedence than operator *=.
x*=y; works like x=x*y;
and here x*=(y+1) is getting expanded like x = x * (y + 1);
*= and similar ones are a type of C assignment operators, i.e. these operators are different from * and alike.
Now from C operator precedence, these operators have lowest precedence (higher than ,) hence y + 1 will be evaluated first, then *= will be evaluated and result will be assigned to x.
It evaluates as
x = x * (y + 1);
so
x = 2 * (5 + 1) = 12
Take a look at Operators order, you will see why in this case it is evaluated like that.
Here from operator procedure in c you can see
Addition/subtraction assignment has lower procedure than simply add operation.
so here
x*=y+1;
+ get executed first.
so
x = x * (6)
so x = 2 * 6
x = 12;
What is the difference between increment operator ++ and an addition + operator? Why can't we can use + instead of ++?
What are the advantages of ++/-- operators over +/-? Where exactly are they applicable?
x++;
v.s.
x = x + 1;
The main advantage comes from pre-increment v.s. post increment:
e.g.
x = 1;
y = 1;
a = x + 1; // a is 2, x is 1 - e.g. does not modify x
a = ++x; // a is 1, x is 2
b = y++; // b is 2, y is 2
The major downside is that stuff like
a = ++x + x--;
is undefined behavior. Completely compiler dependent and WILL make life hell for anyone trying to figure out the "bug".
The only difference that is given by the C standard is the number of evaluations of x. For normal variables the difference usually doesn't matter. If the compiler can prove that in x = x + 1 the two evaluations of x should give the same value it might optimize this out.
If x is e.g declared volatile or involves the evaluation of a function, the evaluation must be done twice. Example:
unsigned* f(void);
then
*f() = *f() + 1;
is quite different from
++(*f());
The unary operators (++, --) are mainly there for convenience - it's easier to write x++ than it is to write x = x + 1 for example.
++ can also be used to do a 'pre-increment' or a 'post-increment'. If you write x++ then the value of x is increased and the original value of x is returned. For example:
int a = 0;
int x = 0;
a = x++; // x is now equal to 1, but a is equal to 0.
If you write ++x, x is still incremented, but the new value is returned:
int a = 0;
int x = 0;
a = ++x; // Both a and x now equal 1.
There is also usually a minor difference in the compiler's implementation as well. Post-increment (x++) will do something like this:
Create a temporary variable
Copy x to the temporary variable
Increment x
Return the temporary variable
Whereas pre-increment (++x) will do something like this:
Increment x
Return x
So using pre-increment requires less operations than post-increment, but in modern day systems this usually makes no worthwile difference to be a decent way of optimising code.
You could in fact use addition:
a = a + 1
But most people prefer the shorter version. In some languages it actually avoids the need to copy the value to a new location, but as nneonneo has helpfully pointed out, the C compiler is likely to optimise this for you.
"++" means "plus one"
eg
int x = 5;
x++; // the same as x = x + 1
cout << x; // will print 6
"+" is the known plus operator
++ is a convenience syntax. It does not really add capability to the language, but it adds a way of writing some common operations more concisely.
As a standalone statement a++; is identical to a+=1; is identical to a=a+1;
a++ can be useful in some situations that would otherwise need two statements:
while (a < N) doSomethingWith(a++);
is just a shorter form of
while (a<N)
{
doSomethingWith(a);
a=a+1;
}
I don't think there is anything you can write with an a++ that you couldn't also write with an a=a+1, but you can't just do a 1 for 1 substitution. Sometimes the 2nd form will require more code to be equivalent, since the 1st performs two things: produce the value of a, and then increment a. The a=a+1 form produces the value of a after the increment, so if you need the original value, you need a separate statement to process that first.
The difference between using the increment operator(ie. value++) vs using the addition operator(ie. value + 1) is that the first one sometimes can cause mutation especially if we are accessing a global variable inside a function;
Using increment operator.
// The global variable
var fixedValue = 4;
function incrementer () {
// Only change code below this line
return fixedValue ++;
// Only change code above this line
}
var newValue = incrementer(); // Should equal 5
console.log(fixedValue); // Should print 5
Using addition operator.
// The global variable
var fixedValue = 4;
function incrementer () {
// Only change code below this line
return fixedValue + 1;
// Only change code above this line
}
var newValue = incrementer(); // Should equal 5
console.log(fixedValue); // Should print 4
increment doing on register but addition do by ALU we can use + instead of increment but increment is faster