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

3

14

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 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?

Randy answered 11/6, 2015 at 9:55 Comment(2)
Have you tried 'kings |= (uint64_t)1 << (uint64_t)i;' or 'kings |= 1ULL << i;'?Distributor
@DannyRuijters Didn't think of it. I tried to equate it to the temporary uint64_t instead. Close!Randy
D
25

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;
Deferral answered 11/6, 2015 at 9:59 Comment(0)
F
10

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;
Flame answered 11/6, 2015 at 10:4 Comment(0)
A
3

You need to bitshift a 64 bit integer:

kings |= 1i64 << 59;
Arredondo answered 11/6, 2015 at 9:59 Comment(1)
i64 is a non-standard suffix so it shouldn't be usedSolace

© 2022 - 2024 — McMap. All rights reserved.