FSMaxB
FSMaxB

Reputation: 2490

How to determine maximum required alignment in C99

Is there a portable way that only relies on what the C99 standard provides to find out the maximum required alignment that is needed for any data type.

Like maxalign_t in C++11.

What I'm currently doing is calculating the least common multiple (lcm) of the alignments of int, long int, long long int, double, void * and size_t as best effort way of determining the alignment.

Update: I currently need this for implementing a wrapper around malloc that stores metadata at the beginning of the block of memory and returns a pointer with a higher address than what malloc has returned.

Upvotes: 8

Views: 2028

Answers (2)

RichS
RichS

Reputation: 550

You can determine the maximum supported alignment empirically by allocating several chunks and seeing if each chunk is aligned on a 16, 8, or 4 byte boundary.

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;
}

Calling GetMaxSupportedAlignment() will return 8 on 64-bit operating systems and 4 on many 32-bit systems.

Upvotes: 1

fuz
fuz

Reputation: 93082

There isn't really a good way to do that, which is why maxalign_t was introduced by C11. Though, I cannot imagine an ordinary system where a type with higher alignment requirements than intmax_t exists so you might as well use that and get the right answer for 99% of the systems when maxalign_t is not available.

Upvotes: 3

Related Questions