下面是一个用于计算CRC32的constexpr字符串字面值。
我不得不将字符串字面值中的字符从char
重新解释为unsigned char
。因为在constexpr函数中不允许使用reinterpret_cast
,所以解决方法是手动进行二进制补码转换,但我对此感到有些失望。
是否存在更优雅的解决方案来处理这种操作?
#include <iostream>
class Crc32Gen {
uint32_t m_[256] {};
static constexpr unsigned char reinterpret_cast_schar_to_uchar( char v ) {
return v>=0 ? v : ~(v-1);
}
public:
// algorithm from http://create.stephan-brumme.com/crc32/#sarwate
constexpr Crc32Gen() {
constexpr uint32_t polynomial = 0xEDB88320;
for (unsigned int i = 0; i <= 0xFF; i++) {
uint32_t crc = i;
for (unsigned int j = 0; j < 8; j++)
crc = (crc >> 1) ^ (-int(crc & 1) & polynomial);
m_[i] = crc;
}
}
constexpr uint32_t operator()( const char* data ) const {
uint32_t crc = ~0;
while (auto c = reinterpret_cast_schar_to_uchar(*data++))
crc = (crc >> 8) ^ m_[(crc & 0xFF) ^ c];
return ~crc;
}
};
constexpr Crc32Gen const crc32Gen_;
int main() {
constexpr auto const val = crc32Gen_( "The character code for É is greater than 127" );
std::cout << std::hex << val << std::endl;
}
编辑:在这种情况下,static_cast<unsigned char>(*data++)
就足够了。
m_
中进行索引。 - galop1nchar
转换为unsigned char
- 参见上文。 - ecatmurchar
是一个有符号的8位二进制补码类型,但是这些属性并未被标准所保证。 - CaseyCHAR_BIT
可以大于8;它只需要至少为8(来自C语言5.2.4.2.1,在3.9.1p3中引用)。 - ecatmurchar
是有符号还是无符号的。在gcc中,实际上有一个标志来控制这个属性。如果您要添加128并且它最初是无符号的,则对于足够大的值,您将只会溢出(并包装)。 - Matthieu M.