下面,您将找到一个用于CRC32计算的constexpr字符串文字。
我不得不重新解释从char
到unsigned char
的字符串文字字符。因为reinterpret_cast
在constexpr函数中不可用,所以变通方法是一个小的实用函数,可以手动补充两个补码,但我对它有点失望。
处理这种操作是否存在更优雅的解决方案?
#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++)
就够了。
答案 0 :(得分:9)
标准不保证两个补码;在第3.9.1条中:
7 - [...]整数类型的表示 应使用纯二进制计算系统定义值。 [示例:此国际标准 允许2的补码,1的补码和积分类型的带符号幅度表示。 - 结束 例子]
因此任何假设两个补码的代码都必须手动执行适当的操作。
那就是说,你的转换功能是不必要的(也可能是不正确的);对于有符号到无符号的转换,您只需使用标准积分转换(4.7):
2 - 如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2 n 其中 n 是用于表示无符号类型的位数。 [注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断)。 - 结束记录]
使用static_cast
::
constexpr uint32_t operator()( const char* data ) const {
uint32_t crc = ~0;
while (auto c = static_cast<unsigned char>(*data++))
crc = (crc >> 8) ^ m_[(crc & 0xFF) ^ c];
return ~crc;
}