如何从指针读取字节序列C++一样长

How to read sequence of bytes from pointer in C++ as long?

本文关键字:一样 C++ 指针 读取 字节      更新时间:2023-10-16

我有一个指向char数组的指针,我需要用一个 64 位掩码对每个字节进行 XOR 运算。我认为最简单的方法是将每 8 个字节读取为一个long longuint64_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 上,小端序,最低有效字节将掩码输入数组的第一个字节)