通过在 C 中移动 3 个整数来构造密钥
constructing key by bit shifting 3 integers in C
我想通过移位操作构造一个由 3 个值组成的键:
根据我的理解,我开始的 C 语句代码通过从某些数据变量构造其键来创建散列 table:
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 位 (pos
+isize
) 构建 key
,我会构建它
32+16+16 位 (pos
+isize
+barc
) 将最后 32 位拆分为
isize
和 barc
.
知道怎么做吗?
"pipe operator"实际上是按位或运算符。该代码采用两个(大概)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 位>巴克。有关更多信息,请参阅 here。
我认为你需要的是 bitmasking 的可靠解释。
对于这种特殊情况,您应该在向上移动之前使用 & 运算符屏蔽掉 c->isize 的高 16 位,然后再次使用 & 运算符屏蔽掉 c-> 的高 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
我不会这样做。如果你不是自己设计整个东西,那是不安全的。但是让我们解释一些事情。
My interpretation is that key is a combination of the last 32 digits of c->pos,
一般来说,是的。
which must be a 64 bit unsigned integer, and c->isize, also a 64bit unsigned integer.
没有。您对 pos
和 isize
类型的大小一无所知,它被强制转换为 uint64_t
它可能是任何允许此类强制转换的类型。
我敢打赌这两个值都是 32 位的。第一个值被转换为 64 位类型,因为位移等于或大于类型的宽度是未定义的行为。所以为了安全起见,它被加宽了。
该代码可能会将两个 32 位值打包到一个 64 位值中,否则会丢失信息。
此外,如果它想从重叠的值构造键,它很可能会使用 xor 而不是 or。你的方法不是一个好方法,除非你确切地知道你在做什么。你应该找出你的操作数是什么类型,然后从中选择一种创建键的方法。
我想通过移位操作构造一个由 3 个值组成的键:
根据我的理解,我开始的 C 语句代码通过从某些数据变量构造其键来创建散列 table:
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 位 (pos
+isize
) 构建 key
,我会构建它
32+16+16 位 (pos
+isize
+barc
) 将最后 32 位拆分为
isize
和 barc
.
知道怎么做吗?
"pipe operator"实际上是按位或运算符。该代码采用两个(大概)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 位>巴克。有关更多信息,请参阅 here。
我认为你需要的是 bitmasking 的可靠解释。
对于这种特殊情况,您应该在向上移动之前使用 & 运算符屏蔽掉 c->isize 的高 16 位,然后再次使用 & 运算符屏蔽掉 c-> 的高 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
我不会这样做。如果你不是自己设计整个东西,那是不安全的。但是让我们解释一些事情。
My interpretation is that key is a combination of the last 32 digits of c->pos,
一般来说,是的。
which must be a 64 bit unsigned integer, and c->isize, also a 64bit unsigned integer.
没有。您对 pos
和 isize
类型的大小一无所知,它被强制转换为 uint64_t
它可能是任何允许此类强制转换的类型。
我敢打赌这两个值都是 32 位的。第一个值被转换为 64 位类型,因为位移等于或大于类型的宽度是未定义的行为。所以为了安全起见,它被加宽了。
该代码可能会将两个 32 位值打包到一个 64 位值中,否则会丢失信息。
此外,如果它想从重叠的值构造键,它很可能会使用 xor 而不是 or。你的方法不是一个好方法,除非你确切地知道你在做什么。你应该找出你的操作数是什么类型,然后从中选择一种创建键的方法。