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

23.7k views Asked by At

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?

3

There are 3 answers

0
Arpegius On BEST ANSWER

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;
0
The Paramagnetic Croissant On

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;
0
Jonathan Potter On

You need to bitshift a 64 bit integer:

kings |= 1i64 << 59;