c++ - 在 C++ 中散列原始字节?

标签 c++ hash bit-manipulation bitwise-operators

我想编写一个采用两种类型的函数 T , U这样sizeof(T)+sizeof(U)<=8并得到 uint64_t只需一个接一个地重新解释它们的字节即可。然而这似乎不起作用。我确信有一种更快、更优雅(且正确)的方法来做到这一点,但我不知道。非常感谢任何提示。

#include <cstdint>
#include <iostream>
#include <vector>

template <typename T, typename U>
constexpr auto hash8(T x, U y) {
  static_assert(sizeof(T) + sizeof(U) <= 8);

  uint64_t u = 0;
  uint64_t v = 0;
  auto px = (uint8_t*)&x;
  auto py = (uint8_t*)&y;
  for (auto i = 0; i < sizeof(T); ++i) {
    u |= (uint64_t)px[i];
    u <<= 8;
  }
  for (auto i = 0; i < sizeof(U); ++i) {
    v |= (uint64_t)py[i];
    v <<= 8;
  }

  return u << (sizeof(U) * 8) | v;
}

int main() {
  std::cout << hash8(131, 0) << '\n';
  std::cout << hash8(132, 0) << '\n';
  std::cout << hash8(500, 0) << '\n';
}

最佳答案

由于缺乏详细信息,我无法帮助解决您代码中的问题,但我可以提出一个可能更简单的解决方案。

首先,我建议添加一个检查,以确保参数对象具有唯一的对象表示形式。除非满足这一点,否则哈希将毫无意义。

其次,std::memcpy 可能会让这个更简单:

template <typename T, typename U>
auto
hash8(T x, U y) noexcept {
    static_assert(sizeof x + sizeof y <= sizeof(std::uint64_t));
    static_assert(std::has_unique_object_representations_v<T>);
    static_assert(std::has_unique_object_representations_v<U>);
    std::uint64_t ret{};
    auto ptr = reinterpret_cast<unsigned char*>(&ret);
    std::memcpy(ptr, std::addressof(x), sizeof x);
    ptr += sizeof x;
    std::memcpy(ptr, std::addressof(y), sizeof y);
    return ret;
}

接下来,我们可以将其推广到任意数量的参数(只要它们合适)和不同的返回类型:

template <typename R = std::uint64_t, typename... Args>
auto
hash(Args... args) noexcept {
    static_assert((sizeof args + ...) <= sizeof(R));
    static_assert((std::has_unique_object_representations_v<Args> && ...));
    static_assert(std::has_unique_object_representations_v<R>);
    R ret{};
    auto ptr = reinterpret_cast<unsigned char*>(&ret);
    (
        (
            std::memcpy(ptr, std::addressof(args), sizeof args),
            ptr += sizeof args
        ), ...
    );
    return ret;
}

需要注意的是,即使对象的大小匹配,这样的哈希值在不同系统中也不相同。

附注将函数设置为 constexpr 是没有意义的,因为您使用了常量表达式中不允许的重新解释转换。

关于c++ - 在 C++ 中散列原始字节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71079245/

相关文章:

twitter - 保护桌面应用程序中的用户密码

c++ - CPP、WinAPI - WM_CREATE 从 lParam 获取 CREATESTRUCT* 的正确方法

c++ - 成功调用析构函数或调用 empy 析构函数后出现段错误。 C++

C++:我不明白 'extern' 关键字在我的程序中是如何工作的

c++ - 另一个有序 map 与无序(哈希) map 问题

C# MD5 哈希结果不是预期的结果

比较两个整数列表中每个位置的位数

有条件地设置或清除位

algorithm - 从二进制数中提取奇数位的最佳方法

c++ - 从 std::cin 读取 int_fast8_t 时出现令人惊讶的结果