我有一个指向char
数组的指针,我需要用一个 64 位掩码对每个字节进行 XOR 运算。我认为最简单的方法是将每 8 个字节读取为一个long long
或uint64_t
和 XOR,但我不确定如何。也许投射到long long*
并取消引用?总的来说,我仍然不确定指针,因此任何示例代码也将不胜感激。谢谢!
编辑:示例代码(只是为了显示我想要的,我知道它不起作用):
void encrypt(char* in, uint64_t len, uint64_t key) {
for (int i = 0; i < (len>>3); i++) {
(uint64_t*)in ^= key;
in += 8;
}
}
}
执行异或掩码的直接方法是按字节:
void encrypt(uint8_t* in, size_t len, const uint8_t key[8])
{
for (size_t i = 0; i < len; i++) {
in[i] ^= key[i % 8];
}
}
注意:这里的key
是一个 8 个字节的数组,而不是 64 位数字。这段代码很简单 - 不需要技巧,易于调试。衡量它的性能,如果性能足够好,就完成它。
一些(大多数?)编译器通过矢量化来优化这些简单的代码。也就是说,所有细节(强制转换为uint64_t
等)都由编译器执行。但是,如果您尝试在代码中"聪明",则可能会无意中阻止编译器进行优化。所以试着写简单的代码。
附言您可能还应该使用 restrict
关键字,该关键字目前是非标准的,但可能需要获得最佳性能。我没有使用它的经验,所以没有将其添加到我的示例中。
如果你有一个糟糕的编译器,无法启用矢量化选项,或者只是想玩一玩,你可以把这个版本与强制转换一起使用:
void encrypt(uint8_t* in, size_t len, uint64_t key)
{
uint64_t* in64 = reinterpret_cast<uint64_t*>(in);
for (size_t i = 0; i < len / 8; i++) {
in64[i] ^= key;
}
}
它有一些限制:
- 要求长度能被 8 整除
- 要求处理器支持未对齐的指针(不确定 x86 - 可能会工作)
- 编译器可能会拒绝对此进行矢量化,从而导致性能下降
- 正如 Hurkyl 所指出的,掩码中 8 个字节的顺序不清楚(在 x86 上,小端序,最低有效字节将掩码输入数组的第一个字节)