4

出于教育目的,我正在 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);而不是。只会使用一级间接。问题是 sizeof 运算符在 prepossessing 阶段不可用。

那么定义一个预处理器值的好方法是什么,它将在每个平台上扩展到正确的 size_t 大小?我想我可以检查预定义的宏,但我想知道是否有更好的方法。

4

4 回答 4

4

sizeof是 C 运算符。##是预处理器运算符。后者对前者一无所知。

因此,您最好使用一个宏来引用系统用于寻址的位宽,例如像这样进行测试:

#if UINTPTR_MAX == 0xffffffffffffffff
/* it's 64bits pointers */
#elif UINTPTR_MAX == 0xffffffff
/* it's 32bits pointers */
#endif
于 2013-02-18T14:21:09.787 回答
3

你可以这样做:

size_t (*hashFunc)(void* key, size_t size) = (sizeof(size_t) == 8) ? hash8 : hash4;

eznme 的方法也没有任何问题——编写一个根据size_t. 当然,前提是您不需要该hash4功能用于 64 位实现的其他目的。

关于问题的标题-如果您绝对需要size_t在预处理器时了解,请使用SIZE_MAX来自stdint.h.

于 2013-02-18T14:21:19.320 回答
1

使用为许多编译器定义的 64 位检测宏,例如 GCC 使用__x86_64

size_t hash(void* key, size_t size) {
   #ifdef __x86_64
       compute 64bit hash
   #else
       compute 32bit hash
   #endif
}
于 2013-02-18T14:12:51.033 回答
1

那么定义一个预处理器值的好方法是什么,它将在每个平台上扩展到正确的 size_t 大小?

根据Glibc 手册 | 整数类型的宽度

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 中定义。除了由宽度指定的类型(参见整数)之外,还定义了以下内容:

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 等平台。

于 2018-08-23T22:40:55.127 回答