2016-12-04 1 views
0

Мой вопрос довольно прямой, является ли этот код переносимым?Возможность переноса битов

#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); 

Я не специалист по битам, но я считаю, что этот язык позволяет переносить его. Или, может быть, я должен использовать что-то вроде std::bitset?

ответ

3
  • 1 << counter должно быть (uint64_t)1 << counter в противном случае это не определено поведение, когда counter достигает sizeof(int) * CHAR_BIT (и определяется реализацией, когда один меньше, чем).
  • Даже после фиксации этого цикла будет оцениваться (uint64_t)1 << 64 для некоторых входов, что является неопределенным поведением, поэтому вам нужно добавить предварительные проверки или условие цикла, чтобы это предотвратить.
+0

(uint64_t) 1 << 64 в случае максимального значения нет? Поэтому я не могу знать, нужны ли мне 64 бита для этого случая? 63бит максимум? Знаете ли вы лучший способ проверить это? –

+0

вы могли бы разбить цикл, если 'counter == 64' или что-то –

+0

о, вы правы, это просто ошибка алго. Я ничего не боялся. В любом случае спасибо :) –

Смежные вопросы