void show_node_names() { display_flags |= ShowNodeNames; } // what is "|="?
I'm not sure what "|=" does or what it's called.
Any help?
That statement is a bitwise or assignment.
It is equivalent to doing display_flags = display_flags | ShowNodeNames.
In particular, it will set every bit in display_flags to 1 if the corresponding bit in ShowNodeNames is 1.
The |= operator is a compound assignment operator like += or *=, but using the bitwise OR operator. The line
display_flags |= ShowNodeNames;
is equivalent to
display_flags = display_flags | ShowNodeNames;
If you haven't seen the bitwise OR operator, you should read up on it for more details. If you're familiar with it, then you can think of display_flags |= ShowNodeNames; as a way of saying "make all the bits set in ShowNodeNames also set in display_flags."
Hope this helps!
| (which can also be spelt bitor) is the bitwise or operator. It combines the bits of each operand so that each bit of the output is set if the corresponding bit of either operand is set. Compare this with the bitwise and operator, & or bitand, where each bit is set of the corresponding bit of both operands is set.
|= (or or_eq) is the corresponding assignment operator. As with all compound assignment operators, a |= b is equivalent to a = a | b, except that a is only evaluated once. Its effect is to set each bit in a that's set in b, and leave the other bits unchanged.
Related
C++ has logical operations, !a, a && b, a || b applicable to true/false values.
And it has bitwise operations, applicable to all (integer?) types, ~a, a & b, a | b, a ^ b, (a << N, a >> N).
Together with in place mutation operators, a &= b, a |= b, a ^= b, (a <<= b, a >>= b).
What confuses me is that bitwise operations could be acting on bits of bool that are not at all part of the true/false value.
Even doing unnecessary bit operations.
I guess that last fact makes bitwise shifting undefined for bool and that makes me doubt whether all bitwise operations are valid at all.
So, are these equivalent for bool types? ~a == !a, a && b == a & b, a || b == a | b?
For some reason (won't question here) there is no "in-place" logical mutation operators (i.e. a &&= b, a ||= b).
This inspires these questions, are these other bitwise operations valid on bools themselves? are a &= b and a |= b always equivalent to a = a && b and a = a || b respectively?** (no "in-place" xor a = a ^ b?)
Some examples: https://godbolt.org/z/hcccG8c9o
(For simplicity I will assume C++20, i.e. two's complement representation of integer types. What I am writing may technically not hold prior to C++20 for all theoretically possible conforming representations of integer types.)
What confuses me is that bitwise operations could be acting on bits of bool that are not at all part of the true/false value.
The built-in bitwise operations have the usual arithmetic conversions applied to their operands first. For integral operands that implies integral promotions: Operands with a conversion rank below that of int are converted to int first (or unsigned int or a higher rank integral type if int can't hold all values of the original type).
The promotion always leaves the original value unchanged. In the case of bool, true is mapped to 1 and false to 0. So the result after promotion will have its least significant bit either set or unset, while all other bits are unset. Also, there are always at least 15 such bits, because int must be at least 16 bit wide.
As a consequence ~a == !a is always false. ~ will set these additional bits, while promotion of !a will not. However bool(~a) == bool(!a) is true only if a is false, because with additional bits set bool(~a) is always true.
a && b == a & b is always true, because additional bits will be zero when & is applied.
a || b == a | b is always true, because additional bits will again remain zero.
However, if a and b are actual expressions, then there is another difference in that the logical operators short-circuit evaluation, while the bitwise ones don't. Therefore, the side effects may be different.
Also, the result of the logical operators will be a bool, while that of the bitwise ones will be a int. Therefore they are not interchangeable as they might e.g. affect overload resolution where their result is used.
Also, this applies only for the built-in operators. If any overloaded operators are involved, nothing is guaranteed.
I am new to c++ and haven't seen such a declaration in programs anywhere. Please help me
For integral type
i >>= 3;
is equal to:
i = i >> 3;
ie bitwise shift variable i right (in his case) in place.
For user defined classes it can be overloaded to whatever functionality author wants this operator to implement
Use of compound assignment operators is encouraged since it evaluates the LHS only once.
From the C++11 Standard:
5.17 Assignment and compound assignment operators
...
7 The behavior of an expression of the form E1 op = E2 is equivalent to E1 = E1 op E2 except that E1 is evaluated only once.
If you have a function that returns a reference to an object, it is more efficient and less error prone when you use a compound assignment operator.
E.g.
std::vector<int> v(10, 1);
v[4] <<= 2;
is better than
std::vector<int> v(10);
v[4] = v[4] << 2;
those are called compound assignment operators. There are almost 10 of them in C/C++ language. ex += -= *= <<= >>=. When one of the operand is same as the variable to which final result to be assigned is same, in a binary operation this can be used as a short hand syntax. Ex a=a+b can be written as a+=b. in the same a=a<<2 can be written as a<<=2. This type of syntactic sugar is also supported by other languages too.
Left shift assignment <<=
x <<= y Shift x left by y bits
Right shift assignment >>=
x >>= y Shift x right by y bits
Read This to know more about bitwise operators in c++.
In c in general, an operator with an equals following it is shorthand for "do the operation, and put the result back in the same variable."
x = x >> 4; // shift x right by 4 bits
x >>= 4; // exactly the same as above
x <<= 3; // shift x left by 3 bits
This assumes that x is a numeric type like long, unsigned short, etc.
If x is not numeric, then the original programmer probably defined the operation as an overloaded operator in c++, for example, lopping off n characters from a string.
The following piece of code compiles with g++ and not gcc, and am stuck wondering why?
inline unsigned FloatFlip(unsigned f)
{
unsigned mask = -int(f >> 31) | 0x80000000;
return f ^ mask;
}
I would assume that in C++,
int(f >> 31)
is a constructor but that leaves me wondering why it's included in the code. Is it necessary?
C doesn't support the C++ "function-style" casting. You need to write it like this
unsigned mask = -(int)(f >> 31) | 0x80000000;
See cast operator
You can use C syntax (int)(f>>31), it will work for both as this C-syntax is C++-compliant.
As the other answers discussed, int(f >> 31) is a C++ function-style cast, and it has the same meaning as the C-style (int) (f >> 31).
How is this cast important?
Actually, this code looks like it's trying to be too clever. f >> 31 retains only the highest-order bit in f, so it's either 1 or 0. The code then casts it to an int and performs unary negation on it, giving you either -1 or 0, and finally bitwise-OR's the result with 0x80000000, which sets the highest bit and then stores the result into mask. Assuming a two's complement system, -1's representation is 0xFFFFFFFF and so mask will become 0xFFFFFFFF if the highest-order bit of f is set, and 0x80000000 otherwise.
The problem, however, is that ints do not have to use two-complement. If the system is one's complement, for instance, -1's representation would be 0xFFFFFFFE, and if the system is sign-magnitude, -1 would be 0x80000001, and mask will have the wrong value.
The irony is that unary negation for unsigned operands is well-defined to do what the author of this code presumably wanted to do, in ยง5.3.1 [expr.unary.op]/p8 of the standard:
The operand of the unary - operator shall have arithmetic or unscoped
enumeration type and the result is the negation of its operand.
Integral promotion is performed on integral or enumeration operands.
The negative of an unsigned quantity is computed by subtracting its
value from 2n, where n is the number of bits in the promoted operand.
The type of the result is the type of the promoted operand.
In other words, assuming 32-bit ints, -1u is defined to be 0xFFFFFFFFu. The cast to int is not just superfluous, it actually causes the code to be nonportable.
When writing code like this in C++:
bool allTrue = true;
allTrue = allTrue && check_foo();
allTrue = allTrue && check_bar();
check_bar() will not be evaluated if check_foo() returned false. This is called short-circuiting or short-circuit evaluation and is part of the lazy evaluation principle.
Does this work with the compound assignment operator &=?
bool allTrue = true;
allTrue &= check_foo();
allTrue &= check_bar(); //what now?
For logical OR replace all & with | and true with false.
From C++11 5.17 Assignment and compound assignment operators:
The behavior of an expression of the form E1 op = E2 is equivalent to E1 = E1 op E2 except that E1 is evaluated only once.
However, you're mixing up logical AND which does short-circuit, and the bitwise AND which never does.
The text snippet &&=, which would be how you would do what you're asking about, is nowhere to be found in the standard. The reason for that is that it doesn't actually exist: there is no logical-and-assignment operator.
The short-circuit (i.e. lazy) evaluation is only for logical && and ||. Bitwise & and | evaluate both arguments.
No, they do not cut-short.
Note that the &= and |= operators are formed as &+= and |+=. Bit operators & and | does not perform shortcut evaluation.
Only boolean operators && and || perform it.
It means, that a shortcutting operator would have to be traditionally named &&= and ||=. Some languages provide them. C/C++ does not.
The code allTrue &= check_foo(); is equivalent to allTrue = allTrue & check_foo()
In which you are using bitwise AND and no lazy evaluation is performed.
The bitwise AND must take two arguments who's binary representation has the same length, and useslogical AND operation to compare each corresponding pair of bits.
First: a &= b; is not the same as a = a && b;. a &= b; means a = a & b;. In C/C++ there is no a &&= b;.
Logical AND a && b is bit like a test for 1 bit. If the first "bit" is already 0, than the result will always be 0 no matter the second. So it is not necessary to evaluate b if the result is already clear from a. The C/C++ standard allows this optimization.
Bitwise AND a & b performs this test for all bits of a and b. So b needs to be evaluated if at least one bit in a would be non-zero. You could perhaps wish that if a==0, than b would not be evaluated, but this optimization is not allowed in C/C++.
Since & is a bit operation, check_foo()` will be evaluated irrespective of value of result
result = false;
result &= check_foo(); // check_foo() is needless called
However, check_foo() will not be called if you use && and result is false as in:
result = false;
result = result && check_foo(); // check_foo() is not called, the bitwise operator shortcircuits
I know the names of most of the operators but not sure what operator<< and operator>> are called.
i.e.
operator=() // the assignment operator
operator==() // the equality of comparison operator
operator++() // the increment operator
operator--() // decrement operator etc.
operator<() // the less-than operator
and so forth...
<< is both the insertion operator and the left-shift operator.
>> is the extraction operator and the right-shift operator.
In the context of iostreams, they are considered to be stream insertion/extraction. In the context of bit-shifting, they are left-shift and right-shift.
In C++ Streams,
<< is insertion operator.
>> is extraction operator.
In Binary Operations,
Right shift (>>)
Left shift (<<)
<< left shift
>> right shift
<< = Bitwise left shift
>> = Bitwise right shift
Bit Shift Operators
The original names were left shift operator (<<) and right shift operator (>>), but with their meanings perverted by streams into insertion and extraction, you could argue that even in bitwise operations << inserts bits on the right while >> extracts them. Consequently, I almost always refer to them as the insertion and extraction operators.
<< is the 'left-shift' operator. It shifts its first operand left by the number of bits specified by its second operand.
They are called the Guillemet Left and Guillemet Right symbols :)