【问题标题】:What's an efficient way to calculate the hash code of a C Union?计算 C 联合的哈希码的有效方法是什么?
【发布时间】:2018-06-23 01:15:04
【问题描述】:

对于下面给定的 C UNION,计算哈希码的有效方法是什么?我应该使用内存中的原始二进制数据吗?还是我应该尝试解释 UNION 的内容来计算哈希码?

#ifdef AF_INET6

#define SOCKADDR        union { \
                            struct sockaddr_in him4; \
                            struct sockaddr_in6 him6; \
                        }

#define SOCKADDR_LEN    (ipv6_available() ? sizeof(SOCKADDR) : \
                         sizeof(struct sockaddr_in))

#else

#define SOCKADDR        union { struct sockaddr_in him4; }
#define SOCKADDR_LEN    sizeof(SOCKADDR)

#endif

我尝试将其转换为 (struct sockaddr_in *) 并使用 sa_in->sin_addr.s_addrsa_in->sin_port。但这感觉不对。我完全忽略了struct sockaddr_in6。我应该只使用原始内存数据吗?怎么样?


struct sockaddr_in6 {
               sa_family_t     sin6_family;   /* AF_INET6 */
               in_port_t       sin6_port;     /* port number */
               uint32_t        sin6_flowinfo; /* IPv6 flow information */
               struct in6_addr sin6_addr;     /* IPv6 address */
               uint32_t        sin6_scope_id; /* Scope ID (new in 2.4) */
           };

           struct in6_addr {
               unsigned char   s6_addr[16];   /* IPv6 address */
           };

struct sockaddr_in{  
    short sin_family;  
    unsigned short sin_port;  
struct in_addr sin_addr;  
    char sin_zero[8];  
};  

【问题讨论】:

  • C++ 和 C 中的实际解决方案会有所不同,并且联合在两者之间没有几乎相同的语义。所以选择你实际使用的一种语言。
  • 第一个union 中的数据大小会因您处理的属性而异。在不知道所涉及的实际大小的情况下,您无法对其进行散列。 sizeof(SOCKADDR) 为您提供最大大小,而不是实际存储在其中的大小。
  • “来自 C++ 的人可能也知道这一点......” C++ 的答案可能会以“不要使用联合”开头。

标签: c hash hashmap hashtable


【解决方案1】:

您必须解释联合的实际内容,至少在一般情况下。原因很简单,部分可能未被使用,即对联合体的有效价值没有贡献。例如,结构可能在成员之间具有填充以对齐成员。对于联合,当不同的联合成员具有不同的大小时,您可以轻松地在末尾添加填充。如果您忽略这一点,则在所有实际用途中都相等的联合将具有不同的哈希值。

【讨论】:

  • 将我的 SOCKADDR 转换为 (struct sockaddr_in *) 并获取 ip 和端口进行哈希处理是否正确?
  • 是的,你可以这样做。对于 IPv4,端口应该是 16 位数字,IP 地址应该是 32 位数字或四个 8 位数字。
  • 但是如果不是 IPv4 会发生什么?还有一个struct sockaddr_in6。这让我很害怕。我可以无所畏惧地施放吗?
  • @LatencyFighter:您必须仅对与当前存储在联合中的值相关的字段进行哈希处理。当前值内的任何填充都有不确定的值;当前值末尾之外的任何填充都具有不确定的值。两者都不是很好的散列材料。我不相信有任何类型可以转换为明确安全的。你需要一个可区分的联合,并且哈希需要对当前存储的值敏感。
  • 好吧,您必须检查sa_family_type 字段以断言它是IP v4。而且,如果不是,您的代码应该要么大声失败,要么相应地处理这种情况。
猜你喜欢
  • 2015-05-28
  • 2010-12-22
  • 1970-01-01
  • 1970-01-01
  • 2021-06-26
  • 1970-01-01
  • 2016-06-23
  • 2011-06-26
  • 2022-07-06
相关资源
最近更新 更多