我正在C中创建一个哈希表的实现,用于教育目的。
哈希函数应返回size_t哈希值。由于size_t的大小在不同的平台上是不同的(我想使用散列函数来散列size_t中的所有位),我想到为不同的大小创建不同的散列函数。由于哈希函数将用作函数指针,我怀疑编译器不能像这样内联代码:
size_t hash4(void* key, size_t size);
size_t hash8(void* key, size_t size);
size_t hash(void* key, size_t size)
{
if (sizeof(size_t) == 4)
{
return hash4(key, size);
}
else if (sizeof(size_t) == 8)
{
return hash8(ket, size);
}
}
size_t (*hashFunc)(void* key, size_t size) = hash;
每次调用哈希函数时都会使用两级间接。
这就是我想做这样的事情的原因:size_t (*hashFunc)(void* key, size_t size) = hash##sizeof(size_t);
。只使用一个间接级别。问题是在prepossessing阶段期间sizeof运算符不可用。
那么定义一个预处理器值的好方法是什么,它将在每个平台中扩展到size_t的正确大小?我想我可以检查预定义的宏,但我想知道是否有更好的方法。
答案 0 :(得分:3)
sizeof
是一个C运算符。 ##
是预处理程序运算符。后者对前者一无所知。
所以你最好使用一个宏来引用用于寻址的系统位宽,例如像这样的测试:
#if UINTPTR_MAX == 0xffffffffffffffff
/* it's 64bits pointers */
#elif UINTPTR_MAX == 0xffffffff
/* it's 32bits pointers */
#endif
答案 1 :(得分:1)
使用为许多编译器定义的64位检测宏,例如:海湾合作委员会使用__x86_64
size_t hash(void* key, size_t size) {
#ifdef __x86_64
compute 64bit hash
#else
compute 32bit hash
#endif
}
答案 2 :(得分:1)
你可以这样做:
size_t (*hashFunc)(void* key, size_t size) = (sizeof(size_t) == 8) ? hash8 : hash4;
eznme的方法也没有任何问题 - 根据size_t
的大小编写一个行为不同的函数。前提是你在64位实现上不需要hash4
函数用于其他目的。
关于问题的标题 - 如果您在预处理器时间绝对需要了解size_t
,请使用SIZE_MAX
中的stdint.h
宏。
答案 3 :(得分:0)
那么定义在每个平台中扩展为size_t正确大小的预处理器值的好方法是什么?
根据Glibc manual | Width of an Integer Type:
TS 18661-1:2014为整数类型的宽度定义了宏( 值和符号位的数量)。这些宏的好处之一是它们 可以在#if预处理程序指令中使用,而sizeof则不能。的 在limits.h中定义了以下宏。
CHAR_WIDTH SCHAR_WIDTH UCHAR_WIDTH SHRT_WIDTH USHRT_WIDTH INT_WIDTH UINT_WIDTH LONG_WIDTH ULONG_WIDTH LLONG_WIDTH ULLONG_WIDTH
这些是char,signed char,unsigned char, short int,unsigned short int,int,unsigned int,long int,unsigned long int,long long int和unsigned long long int。
更多此类宏在stdint.h中定义。除了那些 由width指定的类型(请参阅Integers),定义了以下内容:
INTPTR_WIDTH UINTPTR_WIDTH PTRDIFF_WIDTH SIG_ATOMIC_WIDTH SIZE_WIDTH WCHAR_WIDTH WINT_WIDTH
这些是intptr_t,uintptr_t,ptrdiff_t, sig_atomic_t,size_t,wchar_t和wint_t。
您要寻找的是手册SIZE_WIDTH
。
我不确定MSVC,XLC和SunCC等编译器是否可用;或AIX,OX X,Solaris或Windows等平台。