This question already has answers here:
What is the "-->" operator in C++?
(29 answers)
Closed 8 years ago.
In the question What is the "-->" operator in C++? it asks what --> does and gives a link to a comp.lang.c++.moderated thread. scrolling down the thread a bit further found me this:
> There is no such operator in C++.
> It's just a combination of two operators: postfix decrement "--" and
> greater ">".
> That's why this example works.
> Try ( x --> 20 ) and you'll get no output in this case;)
Of course there is. It is described together with "runs to" operator:
#include <stdio.h>
int main()
{
int x = 10;
while( x -->> 0 ) // x runs to 0
printf("%d ", x);
}
What does the "runs to" operator actually do?
while( x -->> 0 ) // x runs to 0
This is actually a hybrid of the -- (post-decrement) and >> (bitshift right) operators, better formatted as:
while (x-- >> 0) ...
For this specific usage, with 0 on the right hand side, x is decremented with each loop iteration due to the postfix --, and the prior (pre-decrement) value is shifted right 0 bits by >> 0 which does nothing at all when x is non-negative, so the statement could be simplified to:
while (x--) ...
When x is 1 that's non-zero so found true for the purposes of the while test, then post-decrement reduces it to 0 and the loop executes for the last time (with x being 0 during that iteration); the next time while (x--) is checked with x already 0, the while loop terminates, with x left wrapping to the highest representable value for the unsigned type.
More generally, if you try to use >> on a negative value (e.g. x starts at 0 or a negative value great than INT_MIN, so x-- yields a negative value) the result is implementation defined, which means you have to consult your compiler documentation. You could use your compiler documentation to reason about how it would behave in the loop....
Relevant part of the Standard: 5.8/3:
The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a non-negative value, the value of the result is the integral part of the quotient of E1/2^E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
BTW /- for Visual Studio, per http://msdn.microsoft.com/en-us/library/336xbhcz.aspx, the implementation defined behaviour is "No shift operation is performed if additive-expression is 0.". I can't find anything in the GCC manual about this (would have expected it here).
while( x -->> 0 ) // x runs to 0
No, the "goes to operator" is --> with only one > sign. It decreases x by one and then compares the result to zero.
The -- >> 0 "runs to operator" decreases x and then bitshifts the result rightward by zero. Bitshifting by zero does nothing for nonnegative x, otherwise it's implementation-defined (usually does nothing, but could be random). Zero bitshifted by zero is zero, which is interpreted as false, at which point the loop will terminate.
So it "works" but it's a terrible way of expressing a loop.
-- decrements but returns the value of the variable before it was decremented, >> shifts to the right by the right operand, which is 0 (a.k.a. a no-op), then it implicitly compares the result against 0.
Related
I came across a part of code that I cannot understand.
for (unsigned int i = (x & 0b1); i < x; i+= 2)
{
// body
}
Here, x is from 0 to 5.
What is meant by 0b1? and what would be the answers for eg: (0 & 0b1), (4 & 0b1) etc?
0b... is a binary number, just like 0x... is hex and 0... is octal.
Thus 0b1 is same as 1.
1b0 is illegal, the first digit in those must always be 0.
As previous answers said, it is the binary representation of the integer number 1, but they don't seem to have fully answered your question. This has a lot of layers so I'll briefly explain each.
In this context, the ampersand is working as a bitwise AND operator. i & 0b1 is (sometimes) a faster way of checking if an integer is even as opposed to i % 2 == 0.
Say you have int x = 5 and you'd like to check if it's even using bitwise AND.
In binary, 5 would be represented as 0101. That final 1 actually represents the number 1, and in binary integers it's only present in odd numbers. Let's apply the bitwise AND operator to 5 and 1;
0101
0001
&----
0001
The operator is checking each column, and if both rows are 1, that column of the result will be 1 – otherwise, it will be 0. So, the result (converted back to base10) is 1. Now let's try with an even number. 4 = 0100.
0100
0001
&----
0000
The result is now equal to 0. These rules apply to every single integer no matter its size.
The higher-level layer here is that in C, there is no boolean datatype, so booleans are represented as integers of either 0 (false) or any other value (true). This allows for some tricky shorthand, so the conditional if(x & 0b1) will only run if x is odd, because odd & 0b1 will always equal 1 (true), but even & 0b1 will always equal 0 (false).
I have a problem relative to some C++ code about the !! operator. It gives me an unexpected result and I don't understand why:
int x=-12;
x=!!x;
print("value=",x);
The output of this is 1. But i do not know how. Can anyone explain this ambiguous result?
!!x is grouped as !(!x).
!x is 0 if x is non-zero, and 1 if x is zero.
Applying ! to that reverses the result.
So, !!x can be viewed as a way of setting x to 1 if it's not zero, and remaining at 0 if it's zero. In other words x = !!x is the same as x = x ? 1 : 0.
... !(-12) kindly explain this expression.
It's "logical not of -12". In C++ numeric value 0 is false in logical way, and any non-zero value is true in logical way. This is how C and C++ evaluates numerical values in boolean context, like if (expression) ..., i.e. if (-12) exit(1); will exit your application, because -12 is "true".
When you typecast numeric value to bool type and then back to int, the true will become value 1, but most of the time you can avoid these conversions and use intermediate results of numerical calculations directly, where any non-zero value is "true".
So "not of true" is value false. I.e. !(-12) == false. And !false == true. And you convert the logical value "true" back to int, which will make x == 1.
The !!(numeric_value) is idiomatic way in C++ (and in C too) to "normalize" any numeric value into precisely 0 or 1 (and you may encounter it in source code of many applications).
The "logical" distinction is important, because C++ has also binary operators, where the calculation is working per individual bits, not with value as whole. In "binary" way the "!" operator sibling is ~. Similar example to yours with bit-complement operator x=~~x; would then result into original value -12, because every bit of x is flipped twice, ending with same value as it did start. So ~~x is not something to encounter in regular source, as it's basically "no operation" (contrary to !! which is "no operation" only if the original value was already 0 or 1).
Also this is sometimes source of bugs for people learning the language, as they forget about the distinction and write something like
if (4 & 2) { /* this is "and" so it should be true??? */ }
// it will be false, because in binary way 4&2 == 0
if (4 && 2) { /* this is logical "and" and will be "true" */ }
// because 4 is non-zero, 2 is non-zero, and "true and true" is "true"
I.e. binary operators are & | ~ ^ (and, or, not, xor), and their logical siblings are && || ! for "and, or, not", the logical "xor" doesn't have operator in C++.
This question already has answers here:
Comparing a variable to a range of values
(7 answers)
Closed 3 years ago.
int n = 5;
if(2<=n<=20)
{
cout << "hello";
}
In the above code, it does not give an error, it runs successfully and gives "hello" as output.
But we have to use && in this kind of equation.
Can anyone explain this?
<= is left-associative in C++, so the expresion is parsed as ((2 <= n) <= 20). 2 <= n is of type bool, which can implicitly convert to int: true converts to 1 and false converts to 0.
Both of these are <= 20, so the condition is effectively always true.
Note that the above assumes n is an int or another primitive numerical type. If n is a user-defined class with operator <= overloaded, the associativity bit is still true, but the part about implicit conversions may or may not apply, based on the return type and semantics of that overloaded operator.
2<=n<=20 will be executed as (2<=n)<=20.
2<=n results in 0 or 1, depending on the value of n.
0<=20 and 1<=20 are true, so the cout will be executed, independent of the value and type of n.
n could be an object of a class with overloaded operators where 2<=n results to something (object to a class or a value >21), which compared with <=20 results to false. In this case there would be no output.
You probably mean
if (2 <= n && n <= 20)
C++ and C group 2 <= n <= 20 as (2 <= n) <= 20; the sub-expression is either 0 (false in C++) or 1 (true), which are both less than or equal to 20, hence the entire expresion is 1 (true). This is true for any primitive non-pointer type n, including a floating point NaN.
The first comparison 2 <= n is evaluated first. This returns true, which is convertible to an int. From conv.integral#2:
If the source type is bool, the value false is converted to zero and the value true is converted to one.
Once true is converted to 1 or 0, the next comparison is 1 <= 20 or 0 <= 20 which is always true. Hence the output.
I have written this C++ program, and I am not able to understand why it is printing 1 in the third cout statement.
#include<iostream>
using namespace std;
int main()
{
bool b = false;
cout << b << "\n"; // Print 0
b = ~b;
cout << b << "\n"; // Print 1
b = ~b;
cout << b << "\n"; // Print 1 **Why?**
return 0;
}
Output:
0
1
1
Why is it not printing the following?
0
1
0
This is due to C legacy operator mechanization (also recalling that ~ is bitwise complement). Integral operands to ~ are promoted to int before doing the operation, then converted back to bool. So effectively what you're getting is (using unsigned 32 bit representation) false -> 0 -> 0xFFFFFFFF -> true. Then true -> 1 -> 0xFFFFFFFE -> 1 -> true.
You're looking for the ! operator to invert a boolean value.
You probably want to do this:
b = !b;
which is logical negation. What you did is bitwise negation of a bool cast to an integer. The second time the statement b = ~b; is executed, the prior value of b is true. Cast to an integer this gives 1 whose bitwise complement is -2 and hence cast back to bool true. Therefore, true values of b will remain true while false values will be assigned true. This is due to the C legacy.
As pretty much everyone else has said, the bool is getting promoted to an integer before the complement operator is getting its work done. ~ is a bitwise operator and thus inverts each individual bit of the integer; if you apply ~ to 00000001, the result is 11111110. When you apply this to a 32-bit signed integer, ~1 gives you -2. If you're confused why, just take a look at a binary converter. For example: http://www.binaryconvert.com/result_signed_int.html?decimal=045050
To your revised question:
False to true works for the same reason as above. If you flip 00000000 (out to 32 bits), you get 11111111... which I believe is -1 in integer. When comparing boolean values, anything that is -not- 0 is considered to be true, while 0 alone is false.
You should use logical operators, not binary operators. Use ! instead of ~.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Best way to detect integer overflow in C/C++
If I have an expression x + y (in C or C++) where x and y are both of type uint64_t which causes an integer overflow, how do I detect how much it overflowed by (the carry), place than in another variable, then compute the remainder?
The remainder will already be stored in the sum of x + y, assuming you are using unsigned integers. Unsigned integer overflow causes a wrap around ( signed integer overflow is undefined ). See standards reference from Pascal in the comments.
The overflow can only be 1 bit. If you add 2 64 bit numbers, there cannot be more than 1 carry bit, so you just have to detect the overflow condition.
For how to detect overflow, there was a previous question on that topic: best way to detect integer overflow.
For z = x + y, z stores the remainder. The overflow can only be 1 bit and it's easy to detect. If you were dealing with signed integers then there's an overflow if x and y have the same sign but z has the opposite. You cannot overflow if x and y have different signs. For unsigned integers you just check the most significant bit in the same manner.
The approach in C and C++ can be quite different, because in C++ you can have operator overloading work for you, and wrap the integer you want to protect in some kind of class (for which you would overload the necessary operators. In C, you would have to wrap the integer you want to protect in a structure (to carry the remainder as well as the result) and call some function to do the heavy lifting.
Other than that, the approach in the two languages is the same: depending on the operation you want to perform (adding, in your example) you have to figure out the worst that could happen and handle it.
In the case of adding, it's quite simple: if the sum of the two is going to be greater than some maximum value (which will be the case if the difference of that maximum value M and one of the operands is greater than the other operand) you can calculate the remainder - the part that's too big: if ((M - O1) > O2) R = O2 - (M - O1) (e.g. if M is 100, O1 is 80 and O2 is 30, 30 - (100 - 80) = 10, which is the remainder).
The case of subtraction is equally simple: if your first operand is smaller than the second, the remainder is the second minus the first (if (O1 < O2) { Rem = O2 - O1; Result = 0; } else { Rem = 0; Result = O1 - O2; }).
It's multiplication that's a bit more difficult: your safest bet is to do a binary multiplication of the values and check that your resulting value doesn't exceed the number of bits you have. Binary multiplication is a long multiplication, just like you would do if you were doing a decimal multiplication by hand on paper, so, for example, 12 * 5 is:
0110
0100
====
0110
0
0110
0
++++++
011110 = 40
if you'd have a four-bit integer, you'd have an overflow of one bit here (i.e. bit 4 is 1, bit 5 is 0. so only bit 4 counts as an overflow).
For division you only really need to care about division by 0, most of the time - the rest will be handled be your CPU.
HTH
rlc