Здравствуйте, pepsicoca, Вы писали:
P>>>>Посоветуйте, какую хэш-функцию лучше взять, чтобы было быстро и переносимо. WM>>>Кастуй указатель к uintptr_t, и возвращай это значение.
P>>Кстати это мысль. В типичном случае платформы х86 при выделении памяти в куче указатели отличаются в младших разрядах.
В типичной x86 у почти всех адресов структур в младшем бите стоит 0. И в следующем бите тоже. Не ноль там только в разных указателях на упакованные структур, да в указателях на подстроки.
WM>>>Если тебе известно, что от хэш-функции чаще используются младшие биты, то можно сдвинуть (циклически или даже просто так) результат вправо на число бит, равное логарифму типичного выравнивания при выделении памяти (скорее всего будет равно чему-то вроде 2-х или 3-х бит).
P>>Зачем вправо? P>>Вправо сдвинуть значит потерять различия в близкорасположеных указателях. Как раз тогда и будет плохое распределение, все хеш-значения будут одинаковыми. P>>Может влево?
P>А, понял почему. При суммировании может и неважно, а при приведении к типу uintptr_t может помочь. P>Но переносимо никак не узнать, какой шаг выравнивания на данной платформе.
И не нужно. Во-первых, log₂ sizeof int даст хорошее приближение. Во-вторых, циклический сдвиг гарантирует, что мы не потерям информацию, даже если слегка ошибёмся. В-третьих, можно получить нужные параметры и извне. Ну и в-четвёртых, читай следующую строчку: WM>>>Ну или можно дальше вокруг значения типа uintptr_t сделать этап обычного целочисленного хэширования.
Целочисленное хэширование как раз размазывает все биты, и работает вполне универсально. Просто обычно без него можно обойтись. Но если хочется гарантий, то задействуй его — это не дорого.