2013-02-18 4 views
3

Я создаю реализацию хэш-таблицы в C для образовательных целей.size of_t препроцессор значение

Хеш-функция должна возвращать хэш-размер 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 на каждой платформе? Думаю, я мог бы проверить предопределенные макросы, но мне интересно, есть ли лучший способ.

ответ

1

Вы можете сделать это:

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.

+0

Видимо, я могу использовать его для инициализации постоянных указателей функций внутри структуры, поэтому, я думаю, я предпочитаю это на самом деле. –

2

Используйте 64-битный макрос обнаружения, как определено для многих компиляторов, например. GCC использует __x86_64

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

В этом случае, если вы напишете 'if (sizeof (size_t) == 8)', то при любом уровне оптимизации испущенный код фактически не выполнит тест, и компилятор устранит ту ветвь, которая мертва. Однако вам нужны обе ветви для компиляции. –

3

sizeof является С-оператором. ## - оператор препроцессора. Последний ничего не знает о первом.

Таким образом, вы могли бы быть лучше использовать макрос со ссылкой на битовой ширины системы используется для адресации, как, например, тестирование, как так:

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

Я знаю, что я не могу использовать sizeof в качестве оператора препроцессора (я это написал). Во всяком случае, мне нравится это решение, и я думаю, что я просто использую его вместе с тем, что предлагал eznme. –