c-size_t预处理器值的大小



我正在用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运算符在预处理阶段不可用。

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

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

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

#if UINTPTR_MAX == 0xffffffffffffffff
/* it's 64bits pointers */
#elif UINTPTR_MAX == 0xffffffff
/* it's 32bits pointers */
#endif

您可以这样做:

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

eznme的方法也没有错——根据size_t的大小编写一个行为不同的函数。当然,前提是在64位实现中不需要hash4函数用于其他目的。

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

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

size_t hash(void* key, size_t size) {
   #ifdef __x86_64
       compute 64bit hash
   #else
       compute 32bit hash
   #endif
}

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

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

TS 18661-1:2014定义了整数类型宽度的宏(值和符号位的数目)。这些宏的一个好处是可以在#if预处理器指令中使用,而sizeof不能。这个以下宏在限制中定义。h.

CHAR_WIDTH
SCHAR_WIDTH
UCHAR_WIDTH
SHRT_WIDTH
USHRT_WIDTH
INT_WIDTH
UINT_WIDTH
LONG_WIDTH
ULONG_WIDTH
LLONG_WIDTH
ULLONG_WIDTH

这些是类型char、有符号char、无符号char的宽度,short int,unsigned short int、int、unsigned int、long int、unsunsigned分别为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_,sig_atomic_t、size_t、wchar_t和wint_t。

根据手册,SIZE_WIDTH是您想要的。

我不确定MSVC、XLC和SunCC等编译器的可用性;或AIX、OX X、Solaris或Windows等平台。

#include <cstdint>
#include <limits.h>
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 SIZE_MAX == UINT32_MAX
            return hash4(key, size);
    #elif SIZE_MAX == UINT64_MAX
            return hash8(ket, size);
    #else
            static_assert(false, "Not implemented.");
    #endif
}

参考

  • 数字限制
  • 固定宽度整数类型

相关内容

  • 没有找到相关文章

最新更新