Как определить максимально необходимое выравнивание в C99
Существует ли портативный способ, основанный только на том, что обеспечивает стандарт C99, для определения максимально необходимого выравнивания, необходимого для любого типа данных.
подобно maxalign_t
в C++11.
То, что я сейчас делаю, это вычисление наименьшего общего множителя (lcm
) из рядов int
, long int
, long long int
, double
, void *
а также size_t
как лучший способ определения выравнивания.
Обновление: в настоящее время мне нужно это для реализации оболочки malloc
который хранит метаданные в начале блока памяти и возвращает указатель с более высоким адресом, чем malloc
вернулся.
2 ответа
Не очень хороший способ сделать это, поэтому maxalign_t
был представлен C11. Хотя я не могу представить себе обычную систему, в которой тип с более высокими требованиями к выравниванию, чем intmax_t
существует, так что вы можете использовать это и получить правильный ответ для 99% систем, когда maxalign_t
не доступен.
Вы можете определить максимальное поддерживаемое выравнивание эмпирически, выделив несколько фрагментов и посмотрев, выровнен ли каждый фрагмент на границе 16, 8 или 4 байта.
bool GetConsistentAlignment( std::size_t alignment )
{
const unsigned int chunkCount = 16;
void * places[ chunkCount ];
memset( places, 0, sizeof(places) );
bool consistent = true;
for ( unsigned int ii = 0; ii < chunkCount; ++ii )
{
const std::size_t size = 1024 + rand() % 4096;
void * chunk = malloc( size );
places[ ii ] = chunk;
}
for ( unsigned int ii = 0; ii < chunkCount; ++ii )
{
void * chunk = places[ ii ];
const std::size_t place = reinterpret_cast< const std::size_t >( chunk );
if ( place % alignment != 0 )
{
consistent = false;
}
free( chunk );
}
return consistent;
}
std::size_t GetMaxSupportedAlignment()
{
static std::size_t maxAlignment = 0;
if ( maxAlignment == 0 )
{
std::srand( std::time( 0 ) );
std::size_t alignment = 64;
while ( alignment > 1 )
{
const bool isConsistentAlignment = GetConsistentAlignment( alignment );
if ( isConsistentAlignment )
{
break;
}
alignment /= 2;
}
maxAlignment = alignment;
}
return maxAlignment;
}
призвание GetMaxSupportedAlignment()
вернет 8 в 64-битных операционных системах и 4 во многих 32-битных системах.