我创建了u256
类型定义为
using u256 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
我最初使用此代码:
stringstream stream;
u256 data = _data; // both variables are of the same type
for (int i = 0; i < 5; ++i) {
if (i < info.additional) {
if (i == 4) {
// printf("+ ");
stream << "+ ";
}
else {
uint8_t dataByte = int(data & 0xFF);
data >>= 8;
stream << std::setfill('0') << std::setw(sizeof(char) * 2)
<< std::hex << int(dataByte) << " ";
}
}
else {
stream << " ";
}
}
因此,数字被转换为字符串,每个字节之间(只有前一个字节)之间有一个空格。
但是后来我遇到了字节序问题:字节以相反的顺序打印。
所以我在上面的循环之前添加了此代码:
for(unsigned int i=0;i<31;++i) //loop for putting in the big endian order from little endian
{
data |= int(_data & 0xFF);
_data >>= 8;
data <<= 8;
}
_data=data;
现在,为什么我的256位整数大多打印为00 00 00 00 00
系列?如果我注释掉数字,则会再次以错误的顺序完全打印数字新循环。
BTW,这不是字节序问题;您没有对对象表示进行字节访问。您将其作为256位整数进行操作,只需使用data & 0xFF
一次请求低8位即可。
如果您确实了解目标C实现的字节顺序以及boost
对象的数据布局,则可以使用unsigned char*
以降序的地址有效地对其进行循环。
您之所以介绍字节顺序,是因为它与字节反转相关,这是您要尝试的操作。 但这确实效率很低,只需以另一种方式遍历bigint的字节。
我不愿意推荐一个特定的解决方案,因为我不知道什么将有效地进行编译。但是您可能想要类似的东西
for (outer loop) {
uint64_t chunk = data >> (64*3); // grab the highest 64-bit chunk
data <<= 64; // and shift everything up
// alternative: maybe keep a shift-count in a variable instead of modifying `data`
// Then pick apart the chunk into its component bytes, in MSB first order
for (int = 0 ; i<8 ; i++) {
unsigned tmp = (chunk >> 56) & 0xFF;
// do something with it
chunk <<= 8; // bring the next byte to the top
}
}
在内部循环中,与使用两次移位相比,更有效的方法是使用rotate将高字节移至底部(对于& 0xFF
而言),同时将低字节向上移。Best practices for circular shift (rotate) operations in C++
在外部循环中,如果boost::multiprecision::number
具有任何用于对内置块进行有效索引的API,则IDK;如果是这样,使用它可能会更有效。
我使用了嵌套循环,因为我假设data <<= 8
的编译效率不是很高,(data >> (256-8)) & 0xFF
也不会。但这就是从顶部而不是底部抓取字节的方式。
如果您对一次将8、16或32字节数据转换为十六进制的[[efficiency感兴趣,请参阅How to convert a number to hex?了解某些x86 SIMD方式。 asm应该很容易移植到C ++内部函数。 (您可以使用SIMD混洗来处理从小尾数整数加载后将字节按MSB优先的打印顺序放置。)
您还可以使用SIMD随机播放来分隔成对的十六进制数字,然后像您显然想要的那样存储到内存中。所以我在上面的循环之前添加了此代码:
for(unsigned int i=0,data,_data;i<33;++i)
unsigned i, data, _data
声明类型为unsigned int
的新变量,该变量遮盖了以前的data
和_data
声明。该循环对循环范围以外的data
或_data
无效。 (并且包含UB,因为您无需初始化即可读取_data
和data
。)如果这些变量实际上仍然是外部范围的
u256
变量,除了效率外,我没有看到其他明显的问题,但是也许我也缺少明显的问题。我看起来并不难,因为使用64x 256位移位和32x OR似乎是一个可怕的想法。它的[[可能
bswap
字节反向指令,但是我对此表示怀疑。特别是不能通过boost::multiprecision::number
包装函数的额外复杂化。