Cross-platform ALIGN(x) macro?

前端 未结 2 2046
面向向阳花
面向向阳花 2020-12-13 21:11

I would like to create a struct that has a certain alignment.

I would like to use the same struct definition for both GCC and VisualC++ compilers.

2条回答
  •  抹茶落季
    2020-12-13 21:52

    On Modern Compilers

    The new versions of GCC (4.8.1) and VC++ (VS2013) supports the common syntax of having the attribute between struct and the identifier name. This is perhaps due to the new C++11 standard's introduction of the alignas keyword to do the same job the compilers' alignment attribute does; however, alignas can only make the alignment more stricter than the datatype's natural alignment, while the compiler directive can make it more lenient too.

    Aside: On VS2013 alignof and stdalign.h are unsupported; although VS2015 supports alignof and alignas, it still does not have the header mandated by the C++ standard cstdalign (or its C counterpart); so availability should be checked manually based on the tool chain version. This is perhaps due to the poor support of the C language by Visual Studio. GCC, OTOH, has all of it; header, macros (__alignas_is_defined and __alignof_is_defined) and keywords (alignas and alignof).

    With these information, we can define something that works and has a common syntax across compilers:

    #ifdef _MSC_VER
    #    if (_MSC_VER >= 1800)
    #        define __alignas_is_defined 1
    #    endif
    #    if (_MSC_VER >= 1900)
    #        define __alignof_is_defined 1
    #    endif
    #else
    #    include    // __alignas/of_is_defined directly from the implementation
    #endif
    
    #ifdef __alignas_is_defined
    #    define ALIGN(X) alignas(X)
    #else
    #    pragma message("C++11 alignas unsupported :( Falling back to compiler attributes")
    #    ifdef __GNUG__
    #        define ALIGN(X) __attribute__ ((aligned(X)))
    #    elif defined(_MSC_VER)
    #        define ALIGN(X) __declspec(align(X))
    #    else
    #        error Unknown compiler, unknown alignment attribute!
    #    endif
    #endif
    
    #ifdef __alignof_is_defined
    #    define ALIGNOF(X) alignof(x)
    #else
    #    pragma message("C++11 alignof unsupported :( Falling back to compiler attributes")
    #    ifdef __GNUG__
    #        define ALIGNOF(X) __alignof__ (X)
    #    elif defined(_MSC_VER)
    #        define ALIGNOF(X) __alignof(X)
    #    else
    #        error Unknown compiler, unknown alignment attribute!
    #    endif
    #endif
    

    Example client code using the above

    struct ALIGN(32) MyStruct
    {
        ...
    };
    
    static_assert(ALIGNOF(MyStruct) == 32, "Error: MyStruct not on a 32-byte boundary!");
    

提交回复
热议问题