我想通过使用位移操作构造一个由3个值组成的键:
根据我的理解,我开始的C语句代码通过从某些数据变量构造其键来创建哈希表:
uint64_t key = (uint64_t)c->pos<<32 | c->isize;
我的解释是key
是最后32位的组合
c->pos
,必须是64位无符号整数,c->isize
,也是64位无符号整数。
但我不确定是否是这种情况,也许是|
管道运营商
当应用于位移操作时具有不同的含义。
接下来我要做的是修改构建key
的方式
在变量中包含第三个c->barc
元素。鉴于数量
c->barc
和c->isize
的可能性,我想的是
使用32 + 32位(key
+ pos
)构建isize
,我会构建它
使用32 + 16 + 16位(pos
+ isize
+ barc
)分割最后32位
isize
和barc
。
任何想法如何做到这一点?
答案 0 :(得分:3)
我认为你需要的是bitmasking的可靠解释。
对于这种特殊情况,你应该使用&amp;操作员在将其向上移动之前屏蔽c-> isize的高16位,然后使用&amp;操作符再次掩盖c-> barc的高48位。
让我们看一些图表。
let
c->pos = xxxx_xxxx_....._xxxx
c->isize = yyyy_yyyy_....._yyyy
c->barc = zzzz_zzzz_....._zzzz
where
x, y, and z are bits.
note: underscores are to identify groups of 4 bits.
如果我理解正确,你需要一个像这样的64位数字:
xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_yyyy_yyyy_yyyy_yyyy_zzzz_zzzz_zzzz_zzzz
正确?
正如您所知,我们通过
获得了高32 x |-----32 bits of pos----|---32 0 bits--|
(uint64_t)c->pos<<32 = xxxx_xxxx_...._xxxx_xxxx_0000_...._0000
现在,我们想要按位或者使用以下内容:
|----------32 0 bits----|
0000_0000_...._0000_0000_yyyy_yyyy_yyyy_yyyy_0000_0000_0000_0000
要获得那个号码,我们这样做:
((c->isize & 0xffff) << 16)
because:
c->isize & 0xffff gives
yyyy_yyyy_yyyy_yyyy_yyyy_yyyy_yyyy_yyyy
& 0000_0000_0000_0000_1111_1111_1111_1111
---------------------------------------------
0000_0000_0000_0000_yyyy_yyyy_yyyy_yyyy
and then we shift it left by 16 to get
|--------32 0 bits------|
0000_0000_...._0000_0000_yyyy_yyyy_yyyy_yyyy_0000_0000_0000_0000
现在,最后一部分,
|-------48 0 bits-------|
0000_0000_...._0000_0000_zzzz_zzzz_zzzz_zzz
结果简单明了
(c->barc & 0xffff) =
zzzz_zzzz_zzzz_zzzz_zzzz_zzzz_zzzz_zzzz
& 0000_0000_0000_0000_1111_1111_1111_1111
-------------------------------------------------
0000_0000_0000_0000_zzzz_zzzz_zzzz_zzzz
所以我们把所有这些表达式和按位 - 或者它们放在一起。
uint64_t key = ((uint64_t)c->pos << 32) | ((c->isize & 0xffff) << 16)
| (c->barc & 0xffff);
if we diagram it out, we see
xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_0000_0000_0000_0000_0000_0000_0000_0000
0000_0000_0000_0000_0000_0000_0000_0000_yyyy_yyyy_yyyy_yyyy_0000_0000_0000_0000
or 0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_zzzz_zzzz_zzzz_zzzz
-----------------------------------------------------------------------------------
xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_yyyy_yyyy_yyyy_yyyy_zzzz_zzzz_zzzz_zzzz
答案 1 :(得分:2)
“管道运算符”实际上是一个按位OR运算符。该代码采用两个(可能是)32位整数,其中一个向左移位32位并将它们组合在一起。因此,您将获得一个64位数字。有关按位运算的详细信息,请参阅Wiki。
如果你想从三个32位整数中组合你的密钥,那么你显然必须操纵它们以使它们适合64位。你可以这样做:
uint64_t key = (uint64_t)c->pos<<32 | (c->isize & 0xFFFF0000) | (c->barc & 0xFFFF);
此代码从c-> pos获取32位,将它们移位到64位密钥的高32位,然后取c-> isize的高16位,最后取c-的低16位&GT; BARC。有关详情,请参阅here。
答案 2 :(得分:1)
我不会这样做。如果你不是自己设计整件事,那就不安全了。但是我们来解释一些事情。
我的解释是,密钥是c-> pos,
的最后32位数的组合
一般来说,是的。
必须是64位无符号整数,c-> isize,也是64位无符号整数。
没有。您对isize
和uint64_t
类型的大小一无所知,它会被转换为{{1}},它可能是允许此类演员的任何类型。
我敢打赌,这两个值都是32位。第一个值被转换为64位类型,因为位移等于或大于该类型的宽度是未定义的行为。所以为了保持安全,它会被扩大。
代码可能会将两个32位值打包成一个64位的值,否则会丢失信息。
此外,如果它想从重叠的值构造键,那么最有可能使用xor而不是or。你的方式不是一个好方法,除非你准确地知道你在做什么。你应该找出你的操作数是什么类型,然后从中选择一种创建键的方法。