简体   繁体   中英

Bit shift portability

My question is rather direct, is this code portable?

#include  <cstdint>

#ifndef  ECS_INT
  #define  ECS_INT  uint32_t
#endif

#ifndef  ECS_MAX_NB_COMPONENTS
  #define  ECS_MAX_NB_COMPONENTS  255
#endif

static constexpr uint8_t  FIND_MAX_NUMBER_OF_BITS(uint64_t base) {

  //! Round to upper pow2
  base--;
  base |= base >> 1;
  base |= base >> 2;
  base |= base >> 4;
  base |= base >> 8;
  base |= base >> 16;
  base |= base >> 32;
  base++;

  //! Check bits number
  uint8_t  counter = 0;
  while (!(base & (1 << counter)))
    ++counter;
  return counter;
}

static constexpr const ECS_INT  INVALID_INDEX           = ((ECS_INT) - 1);
static constexpr const uint8_t  ECS_INT_MAX_BITS        = FIND_MAX_NUMBER_OF_BITS(INVALID_INDEX) + 1;
static constexpr const uint8_t  ECS_COMPONENT_MAX_BITS  = FIND_MAX_NUMBER_OF_BITS(ECS_MAX_NB_COMPONENTS);

I'm not an expert about bits but I think the language allow this to be portable. Or maybe I should use something like std::bitset ?

  • 1 << counter should be (uint64_t)1 << counter otherwise it is undefined behaviour when counter reaches sizeof(int) * CHAR_BIT (and implementation-defined when one less than that).
  • Even after fixing that, the loop will evaluate (uint64_t)1 << 64 for some inputs, which is undefined behaviour, so you need to add pre-checks or a loop condition to prevent that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM