Reputation: 83
I want to print all bits of a long long number. When I am doing it in main() everything is fine, but in printBits() function (where code is same) there is an extra 1 on 32th bit.
The code:
#include <iostream>
void printBits(long long number)
{
std::cout<<number<<" -> ";
for (char i=63; i>=0; --i)
{
std::cout<<(bool)(number&(1<<i));
}
std::cout<<std::endl;
}
int main()
{
long long number=1;
std::cout<<number<<" -> ";
for (char i=63; i>=0; --i)
{
std::cout<<(bool)(number&(1<<i));
}
std::cout<<std::endl;
printBits(number);
return 0;
}
Result is:
1 -> 0000000000000000000000000000000000000000000000000000000000000001
1 -> 0000000000000000000000000000000100000000000000000000000000000001
Process returned 0 (0x0) execution time : 0.012 s
Press any key to continue.
Upvotes: 8
Views: 696
Reputation: 92271
The reason for the different results is that the compiler (here clang 6.0) can produce different code in the main function and in printBits
.
In main
it is known that number
is always 1, and never changes. It is also "obvious" that this can only produce a single 1
in the output. So the optimizer rewrites the loop as:
for (char i=64; i > 0; --i)
{
std::cout<< (i == 1 ? 1 : 0);
}
Look ma, no shifts!
The assembly looks like this
012B13CC mov bl,40h ; i = 40h = 64
012B13CE xchg ax,ax ; nop to align the loop
main+30h:
012B13D0 xor eax,eax
012B13D2 cmp bl,1 ; i == 1?
012B13D5 mov ecx,esi
012B13D7 sete al
012B13DA push eax
012B13DB call edi ; edi -> operator<<
012B13DD dec bl
012B13DF jg main+30h (012B13D0h)
In printBits
it cannot optimize this way, as the function could possibly be called from elsewhere. So there it performs the shift (with the erroneous result).
Upvotes: 3
Reputation: 4176
As Cpp plus 1's answer shows you need to modify the (default int) literal 1
to a long long literal 1LL
or 1ll
.
However, you might be better off using std::bitset
instead of your function:
#include <bitset>
long long number = 1; // int number = 1; also works
std::bitset<64> bits(number);
std::cout << number << " -> " << bits << std::endl;
yields:
1 -> 0000000000000000000000000000000000000000000000000000000000000001
The reason you are getting this output is because for the specific hardware/compiler you are using:
a << x
operation works in the following way: a << (x mod (8 * sizeof(a))
. Therefore for 1
you get
1 << (x mod 32)
. This means that on the 32nd loop iteration:
std::cout << (bool)(number & (1 << 32));
// becomes
std::cout << (bool)(number & (1 << 0));
// printing '1'
Upvotes: 3
Reputation: 1010
The literal 1 defaults to an integer. Cast it to long long to solve the problem.
std::cout<<(bool)(number&(((long long)1)<<i));
Upvotes: 4