我编写了一些代码作为练习,它基本上只使用(循环除外)逐位操作对任何大小的数据执行数学运算。它主要是功能性的,但有一个我无法理解的问题,我无法在上下文中重新创建它,并且有一些代码随之而来,但这里的代码片段给我带来了麻烦
const __rint<size> _leftshiftto(__rint<size>arg)
{
if (arg.val[0] & 0x80)//negative arg
{
return _rightshiftto(arg._negto());
}
uint32_t byte = (arg._int32() / 8);
uint32_t carbyte = size - byte;
byte = byte;
uint8_t bit = (arg._int8() % 8);
uint8_t carbit = 8 - bit;
for (uint32_t n = 0; n<carbyte; ++n)
{
puts("iter");
printf("%02hhx <- %02hhx\n",val[n],val[n+byte]);
val[n] = val[n + byte];
}
for (uint32_t n = carbyte; n < size; ++n)
{
puts("iter2");
val[n] = 0x00;
}
for (uint32_t n = 0; n<size-1; ++n)
{
val[n] <<= bit;
val[n] &= val[n + 1] >> carbit;
}
val[size - 1] <<= bit;
return *this;
}
完整代码位于https://github.com/rtpax/rmath/blob/master/rint.h
正在发生的事情是它适用于足够小的值,但对于输入8或更高的值评估为零(所以如果它移动整个字节)。
__rint<4> a(5);
//evaluates to 0x00000005
a._leftshiftto(4);
//evaluates to 0x00000050
__rint<4> b(5);
//evaluates to 0x00000005
b._leftshiftto(8);
//evaluates to 0x00000000
如果更改线路
,更奇怪的是val[n] = 0x00;
到
val[n] = 0xff;//or anything 0x80 and above
它确实有效,除了最右边的字节将填充你放在那里的任何数字(因此上面的b
将评估为0x000005ff
)
我对此感到茫然,如果有人能提供解释我很感激。
其他一些说明:
我正在使用Windows 10上的g ++进行编译
似乎相关的东西是,当我打印出我的六角形时,如果它们至少为0x80(打印为0xff80),则显示为4位数而不是2位数
从1到7的反转也不适用于较大的数字,但我认为这些失败的原因与整个字节转换失败的原因相同。
答案 0 :(得分:0)
&
是逻辑和运算符:它在两个源中都需要1才能在目标中产生1。 0101 & 0011
会产生0001
。
val[n] &= val[n + 1] >> carbit;
这会将val[n]
设置为零,因为我们知道val[n]
的低位为零,我们移位val[n + 1]
位,因此相应的高位将为零:
11111000 &
00000111 =
00000000
您需要|
运算符:
11011000 |
00000010 =
11011010
另请注意,您的代码会修改此对象,但您可以按值返回,制作副本。
您的返回类型可能应为
const __rint<size>&
返回const 值在这里没什么意义。