【问题标题】:How to determine maximum required alignment in C99如何确定 C99 中所需的最大对齐方式
【发布时间】:2016-07-08 16:04:27
【问题描述】:

是否有一种可移植的方式,只依赖于 C99 标准提供的内容来找出任何数据类型所需的最大对齐方式。

就像 C++11 中的 maxalign_t

我目前正在做的是计算intlong intlong long intdoublevoid *size_t 对齐的最小公倍数 (lcm) 作为最大努力确定对齐方式。

更新: 我目前需要这个来实现围绕malloc 的包装器,该包装器将元数据存储在内存块的开头并返回一个地址比malloc 返回的地址更高的指针。

【问题讨论】:

    标签: c c99 memory-alignment


    【解决方案1】:

    没有真正的好方法可以做到这一点,这就是 C11 引入 maxalign_t 的原因。不过,我无法想象一个普通系统,其中存在比intmax_t 具有更高对齐要求的类型,所以当maxalign_t 不可用时,您不妨使用它并为99% 的系统获得正确答案。

    【讨论】:

    • 听到这个消息很难过。我会评估是否可以切换到 C11,否则使用 intmax_t。
    • 为了更加偏执,您可以使用intmax_tlong double 的对齐要求,以较大者为准。
    • @SteveSummit:别忘了void*。 128 位指针类型可以组合有关基地址、大小和偏移量的信息,与使用简单的线性指针相比,可以更有效地捕获错误的指针操作。
    • @FSMaxB 更新我之前的评论:要真正偏执,您可以使用intmax_tlong doublevoid *void (*)() 的最大对齐要求(即最大的整数、最大浮点数、通用数据指针和函数指针类型)。
    • @SteveSummit:这真的能解决问题吗?我认为没有什么会禁止编译器要求,至少对于某些类型,对于 N 的偶数值,T[N] 的对齐要求比 T 更粗略(这样的对齐要求不会影响大小或任何数组的步幅,除了包含数组的某些结构会更大。我认为拥有一个可测试的标准宏将非常有用,编译器可以通过该宏断言数组与底层元素具有相同的对齐方式,但目前有没有办法通过哪些程序...
    【解决方案2】:

    您可以通过分配几个块并查看每个块是否在 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() 将在 64 位操作系统上返回 8,在许多 32 位系统上返回 4。

    【讨论】:

    • 这不是一个真正实用的解决方案,更像是一个深奥的解决方案。您的方法是概率性的,不能保证总是产生相同的结果。它还依赖于堆分配(不太好),它实际上是 C++,而不是 C99。
    猜你喜欢
    • 2020-09-09
    • 1970-01-01
    • 1970-01-01
    • 2018-01-12
    • 2013-08-13
    • 2018-04-06
    • 2013-05-02
    • 1970-01-01
    • 2021-11-23
    相关资源
    最近更新 更多