Как определить максимально необходимое выравнивание в 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-битных системах.

Другие вопросы по тегам