I browsed through the internet and got to know that it is a compound assignment operator. But how does it work?
I used this link to get to know about the definition, but I couldn't find the exact implementation of this syntax.
In the link that you provided, there is a code snippet that uses a compound assignment operator:
a+=2; // equivalent to a=a+2
The >>= operator also works in a similar way:
a>>=2; // equivalent to a=a>>2
>> is called as the (Right) Shift operator, and shifts the source operand's binary representation to the right by a certain number of bits. For instance, let us have this code snippet:
int a=12;
cout<<a<<endl;
a>>=2;
cout<<a<<endl;
The output of the code segment, when executed with a C++ compiler will be:
12
3
What exactly happens is this: a has the value of 12, which is represented in binary as (only showing the last 6 bits) 001100. a>>=2; shifts the bits in a by 2 places to the right and assigns the new value to a, hence the new bit positions become 000011, which is 3 in decimal, and hence a gets the value of 3, and the resulting output.
Hope this clarifies the confusion.
>> is the right shift operator.
As you mentioned >>= is a compound assignment operator. A compound assignment modifies the variable with the operator and assigns the new value to itself.
a >>= b is equivalent to a = a >> b
i.e., a is right shifted b times and assigned back to a.
For example,
int a = 8, b = 2;
a >>= b; // right shift by 2 i.e. divide by 2 x b times.
cout << a; // prints value of 2
Related
Why does an expression i = 2 return 2? What is the rule this is based on?
printf("%d\n", i = 2 ); /* prints 2 */
I am in C domain after spending long time in Java/C#. Forgive my ignorance.
It evaluates to 2 because that's how the standard defines it. From C11 Standard, section 6.5.16:
An assignment expression has the value of the left operand after the assignment
It's to allow things like this:
a = b = c;
(although there's some debate as to whether code like that is a good thing or not.)
Incidentally, this behaviour is replicated in Java (and I would bet that it's the same in C# too).
The rule is to return the right-hand operand of = converted to the type of the variable which is assigned to.
int a;
float b;
a = b = 4.5; // 4.5 is a double, it gets converted to float and stored into b
// this returns a float which is converted to an int and stored in a
// the whole expression returns an int
It consider the expression firstly then print the leftmost variable.
example:
int x,y=10,z=5;
printf("%d\n", x=y+z ); // firstly it calculates value of (y+z) secondly puts it in x thirdly prints x
Note:
x++ is postfix and ++x is prefix so:
int x=4 , y=8 ;
printf("%d\n", x++ ); // prints 4
printf("%d\n", x ); // prints 5
printf("%d\n", ++y ); // prints 9
Assign the value 2 to i
Evaluate the i variable and display it
In C (almost) all expressions have 2 things
1) a value
2) a side effect
The value of the expression
2
is 2; its side effect is "none";
The value of the expression
i = 2
is 2; its side effect is "changing the value in the object named i to 2";
I'm shifting some bits and just realized that doing the operation using a variable doesn't have the same result as using a number. See the example below.
int a = 97;
int b = 0;
b = 1 << a;
printf("%d\n", b);
// 2
b = 1 << 97;
printf("%d\n", b);
// 0 - warning: shift count >= width of type [-Wshift-count-overflow]
Since the result of a left shift with a right operand larger than the length in bits of the left operand is undefined, any result is possible from the expression.
In the variable case (1 << a), since a is 97 (larger than the number of bits in an int), the most likely results are 1 << (97 % 32) == 1 << 1 == 2 or 0, typically depending on how the hardware (CPU) handles these shifts.
With a constant (1 << 97), the compiler knows you're shifting too far, issues the warning (which is not required), and defines the result as 0 (also not required).
The warning you are seeing is a compile time warning. Now, you can clearly see that your int b is a 32-bit variable which will be overflown if left-shifted 97 times. So, it's a valid concern. But the compiler can only detect this overflow for the constant number of shifts as it is evaluated during compilation and the compiler immediately knows that it'll overflow.
In case of variable number of shifts, the compiler isn't smart enough to know what value int a will posses when it'll come down to shifting. So, the compiler leaves it upto you.
The undefined behavior is outlined in the C++ standard here.
http://eel.is/c++draft/expr.shift
The behavior is undefined if the right operand is negative, or greater
than or equal to the width of the promoted left operand.
You'll get different results depending on compiler and optimization level. If you turn on optimization, the compiler will easily optimize out the first shifting operation and then make it 0 as well.
Why exactly does it act like that though? The x86 instruction for shifting by a variable is SAL (shift-arithmetic-left). You can see the instruction list for bit shifting operations here:
https://c9x.me/x86/html/file_module_x86_id_285.html
The one that would be used in an unoptimized build would be SAL r/m32, CL. The CL register is 8 bits, but the processor masks it to 5 bits internally:
The destination operand can be a register or a memory location. The count operand can be an immediate value or register CL. The count is masked to 5 bits, which limits the count range to 0 to 31. A special opcode encoding is provided for a count of 1.
I can't understand these codes for fast integer power of two,
inline constexpr std::uint64_t pow2 (std::uint64_t i)
{
return std::uint64_t(1) << i;
}
In fact, I can't understand how following codes work, uint64_t is just a type, int is also OK,
return std::uint64_t(1) << i;
type(x) in C++ is simply an alternative to the C type conversion (type)x.
So std::uint64_t(1) is equivalent to (std::uint64_t)1 and produces a std::uint64_t with value 1. (Note: std::uint64_t is C++11 or later).
For unsigned integral types, the standard also specifies that left shift n is equivalent to multiplying by 2, n times (i.e. multiplying by 2 to the power of n), as long as overflow of the type does not occur.
For signed types, the result of left shift is not defined for negative values.
The << is the bit shift operator, which essentially multiplies a number by 2 for every 1 in the number.
so 1<<2 = 1*2*2
3<<5= 3*2*2*2*2*2
And multiplying by 2 for each 1 in the number is just raising 2 to a power and multiplying by the original value. (Thanks for the correction M.M)
It's just calling the constructor of unit64_t. You don't normally see it used with basic types like that. Normally constructors are used with user defined classes and one might see something like:
return A(1);
where A is a class defined by the user.
In this case substitute A with std::uint64_t. Then the << multiplies the value 1 by 2 an i number of times.
Someone please tell me the difference between the following codes which add two variables of datatype int. I want to know which one is better.
Code A:
sum = sum + value;
Code B:
sum += value;
We usually prefer ++ operator over += 1. Is there any specific reason behind that as well ?
I want to know the difference between the above codes with respect to the conventions or efficiency level. Which one is recommended ?
While the end result of the e.g. someVar++ operator is the same as someVar += 1 there are other things playing in as well.
Lets take a simple statement like
foo = bar++;
It's actually equivalent (but not equal) to
temp = bar;
bar += 1;
foo = temp;
As for the prefix and suffix increment or decrement operators, they have different operator precedence, which will affect things like pointer arithmetic using those operators.
As for the difference between
foo += 1;
and
foo = foo + 1;
there's no different for primitive types (like int or float) or pointer types, but there's a very big difference if foo is an object with operator overloading. Then
foo += 1;
is equal to
foo.operator+=(1);
while
foo = foo + 1;
is equal to
temp = foo.operator+(1);
foo.operator=(temp);
Semantically a very big difference. Practically too, especially if any of the operator overload functions have side-effects, or if the copy-constructor or destructor have some side-effects (or you forget the rules of three, five or zero).
One calls operators = and + the later calls operator +=.
operators ++ and += are preferred because of readability - most programmers know what they mean.
On the other hand most modern compilers will generate the same code for += 1 as ++ and +/= as += for builtin types;
But for user defined classs, the actual operators will be called and it's up to the implementer of those classs to make sense of it all. In these cases ++ and += can be optimal.
cout << sum++; Would print out the value of sum before it was incremented. Also, depending on what you are doing, you can overwrite the operators += and +.
When you minimize code, you reduce the chance of an error (a typographical error or a logical error).
By using
sum += value;
you reduce the chance - ever so slightly - of an error while typing
sum = sum + value;
The same with value++;
value += 1;
could be more easily confused with
value += l; where l is a variable....
Its more about consistency that it is about right or wrong, but reducing code is a major bonus for maintainability.
Care must be taken with precendence of operators however, in complex statements.
In the case shown there's no particular reason to prefer one method of incrementing the value over another except perhaps for readability purposes. In this case I think I'd prefer sum += value over sum = sum + value as it's a bit briefer and (I think) clearer, but YMMV on that.
As far as prefering ++ over += 1, (IMO again) ++ is preferable when incrementing a value as part of an expression, e.g. sum += array[index++] - but if the entire point of what's being done is adding one to a value I'd prefer index += 1. But let's face it, a great deal of this is personal preference and spur-of-the-moment choice. I always try to write what I think, at that moment, is the simplest and clearest code possible - but I must admit that when I go back and read some of my own code later I have more "What was I thinkin'?!?" moments than I'd care to admit to. :-)
YMMV.
Best of luck.
Code A and B do the same thing. The advantage to using Code B is that it's quicker to type and easier to read.
As for using the ++ operator over += 1, again it is for readability. Although there is a difference between foo++ and ++foo. The former is read first and then incremented, while the latter is incremented first and then read from.
A compound assignment expression of the form E1 op= E2 is equivalent
to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1
is evaluated only once.
An example cited from Java's +=, -=, *=, /= compound assignment operators
[...] the following code is correct:
short x = 3;
x += 4.6;
and results in x having the value 7 because it is equivalent to:
short x = 3;
x = (short)(x + 4.6);
Its basically the same thing. Its both an operator.
One of it calls = and +. And the other +=..
So if you did value +=5. Value goes up by 5. += is better and more organized. And shortens your code whitch is better and more professional.
There is no difference between the two in terms of functionality. A += B actually means A = A + B. The first one is just a shorter way of writing the second.
They both are same up to that, both can be used for incrementing the value of a variable (stored in it).
x++ will increment the value of x by one (1) every run time.
+= adds right operand to the left operand and stores the result in left operand.
Something like following:
C += A is just same as C = C + A
The difference between both ++ and += is that the first can increment by one (1) only, while += can be used to increment more than one in just one line.
e.g:
x += 1; // will increment by 1 every run time
x += 4; // will increment by 4 every run time
x += 10; // will increment by 10 every run time
Consider the following snippets:
C++:
#include <iostream>
using namespace std;
int main()
{
int x = 10, y = 20;
y = x + (x=y)*0;
cout << y;
return 0;
}
which gives a result of 20, because the value of y is assigned to x since the bracket is executed first according to the Operator Precedence Table.
VB.NET:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim x As Integer = 10
Dim y As Integer = 20
y = x + (x = y) * 0
MsgBox(y)
End Sub
which instead gives a result of 10.
What is the reason for this difference?
What is the order of execution of operators in VB.NET?
Unlike in C++, VB.NET's = is not always an assignment. It can also be the equality comparison operator (== in C++) if it appears inside an expression. Therefore your two expressions are not the same. They are not even equivalent. The VB.NET code does not do what you might think it does.
First to your C++ code: Like you're saying, the assignment x=y happens first; thus your code is roughly equivalent to this: (It seems that was incorrect; see Jens' answer.) Since you end up with y being 20, it is likely that your C++ compiler evaluated your code as if you had written this:
int x = 10, y = 20;
x = y;
y = x + x*0; // which is equivalent to `y = 20 + 20*0;`, or `y = 20 + 0;`, or `y = 20;`
In VB.NET however, because the = in your subexpression (x=y) is not actually interpreted as an assignment, but as a comparison, the code is equivalent to this:
Dim x As Integer = 10
Dim y As Integer = 20
y = 10 + False*0 ' which is equivalent to `y = 10 + 0*0`, or `y = 10` '
Here, operator precedence doesn't even come into play, but an implicit type conversion of the boolean value False to numeric 0.
(Just in case you were wondering: In VB.NET, assignment inside an expression is impossible. Assignments must always be full statements of their own, they cannot happen "inline". Otherwise it would be impossible to tell whether a = inside an expression meant assignment or comparison, since the same operator is used for both.)
Your C++ snippet is undefined behavior. There is no sequence point between using x as the first argument and assigning y to x, so the compiler can evaluate the sub-expressions in any order. Both
First evaluate the left side: y = 10 + (x=y) * 0 -> y = 10 + (x=20) * 0 -> y = 10 + 20*0
First evaluate the right side: y = x + (x=20) * 0 -> y = 20 + 20 * 0
It is also generally a very bad style to put assignments inside expressions.
This answer was intended as a comment, but its length quickly exceeded the limit. Sorry :)
You are confusing operator precedence with evaluation order. (This is a very common phenomenon, so don't feel bad). Let me try to explain with a simpler example involving more familiar operators:
If you have an expression like a + b * c then yes, the multiplication will always happen before the addition, because the * operator binds tighter than + operator. So far so good? The important point is that C++ is allowed to evaluate the operands a, b and c in any order it pleases. If one of those operands has a side effect which affects another operand, this is bad for two reasons:
It may cause undefined behavior (which in your code is indeed the case), and more importantly
It is guaranteed to give future readers of your code serious headaches. So please don't do it!
By the way, Java will always evaluate a first, then b, then c, "despite" the fact that multiplication happens before addition. The pseudo-bytecode will look like push a; push b; push c; mul; add;
(You did not ask about Java, but I wanted to mention Java to give an example where evaluating a is not only feasible, but guaranteed by the language specification. C# behaves the same way here.)