Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitwise (Bitshift) operations on 64-bit integers in C++

I'm trying to deal with bitboards, which requires me to set a particular bit in a 64-bit unsigned integer. To set bit i, I perform a bitwise OR with the bitboard in question, with a left shifted number.

#include <stdint.h>
uint64_t kings = 0ULL; // Also tried unsigned long long int before.
kings |= 1 << i;

It works fine from bit 0 to bit 31, but fails to work for bits 32 to 63. I suspect it's because the evaluation of the right side happens to be in a 32-bit integer. Therefore, I tried a temporary variable.

uint64_t temp = 0ULL;
temp |= 1 << i;

Perhaps it still evaluates the right hand side as a 32-bit integer, or that it's some other problem I cannot figure out. To output the integer, I'm using std::bitset<64>. For example:

uint64_t kings = 0ULL;
kings |= 1 << 3;
kings |= 1 << 59;

Expected decimal value: 576460752303423496

Actual: 8

std::bitset<64> x(kings);
std::cout << x;

Bit value: 0000000000000000000000000000000000000000000000000000000000001000

Clearly, only kings |= 1 << 3; worked correctly.

In summary, what is the issue with bits 32 to 63 and how can I work around it?

like image 509
Shreyas Avatar asked Jun 11 '15 09:06

Shreyas


Video Answer


2 Answers

You need to use 1LL as 64 bit value before you use shift operator << to get 64 bit result:

#include <stdint.h>
uint64_t kings = 0ULL; 
kings |= 1ULL << i;
like image 59
Arpegius Avatar answered Oct 05 '22 07:10

Arpegius


what is the issue with bits 32 to 63?

The literal 1 is of type int. The type of a shift operator's result is the type of its LHS (after usual arithmetic conversions have been performed on it). It appears to be 32 bits on your implementation, so shifting it by more than 31 bits yields undefined behavior.

Use a 64-bit integer as the left operand of the shift operator:

temp |= static_cast<uint64_t>(1) << i;
like image 27
The Paramagnetic Croissant Avatar answered Oct 05 '22 07:10

The Paramagnetic Croissant