跨平台 ALIGN(x) 宏? [英] Cross-platform ALIGN(x) macro?

查看:22
本文介绍了跨平台 ALIGN(x) 宏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个具有特定对齐方式的 struct.

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

我想对 GCC 和 VisualC++ 编译器使用相同的结构定义.

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

在 VisualC++ 中,通常这样做:

In VisualC++, one typically does this:

__declspec(align(32))
struct MyStruct
{
// ...
};

在 GCC 中,通常会这样做:

In GCC, one typically does this:

struct MyStruct
{
// ...
} __attribute__ ((aligned (32)));

我当然可以创建适当的宏来完成这项工作:

I could of course create the appropriate macros to make this work:

BEGIN_ALIGNED_STRUCT(32)
struct
{
// ...
}
END_ALIGNED_STRUCT(32)
;

因此能够透明地处理这两种情况,但在这里我必须复制对齐常量(32),这是我想避免的.

And thus be able to handle both cases transparently, but here I have to duplicate the alignment constant (32), which I'd like to avoid.

GCC 中的替代方法是将 __attribute__ 放在结构标记之后,如 文档,像这样:

An alternative in GCC is to put the __attribute__ after the struct tag, as mentioned in the docs, like so:

struct __attribute__ ((aligned (32))) MyStruct
{
// ...
};

因此我可以使这种类型的语法起作用:

And thus I could make this type of syntax work:

ALIGNED_STRUCT(32) MyStruct
{
// ...
};

谁有更好的版本?其他想法?我尝试了一些代码搜索,但没有找到任何有希望的东西.

Does anyone have any better versions? Other ideas? I tried a little code searching, but didn't find anything too promising.

更新:根据@John 的评论,这是另一个可以工作的版本(我还没有编译它,但文档表明这是一个不错的主意)

Update: Based on @John's comment, here's another version that could work (I haven't compiled it, but the docs indicate it's an OK idea)

struct MyStruct_Unaligned
{
// ...
};

TYPEDEF_ALIGNED(32, MyStruct_Unaligned, MyStruct);

// Would expand to one of:
// 
// typedef __declspec(align(32)) MyStruct_Unaligned MyStruct;
//
// typedef struct __attribute__ ((aligned (32))) MyStruct_Unaligned MyStruct

推荐答案

我知道这个帖子已经很老了 - 但是它还没有被标记为已回答,并且提到的解决方案并不是最容易使用的.解决此问题的最佳方法是注意 MSVC 允许 declspec 出现在声明符之后.这是我自己的实现:

I know this thread is quite old - however it is yet to be marked as answered and the solutions mentioned are not the easiest to use. The best way to solve this is to notice that MSVC allows the declspec to appear after the declarator. Here is my own implementation:

#if defined(_MSC_VER)
#define ALIGNED_(x) __declspec(align(x))
#else
#if defined(__GNUC__)
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#endif

#define _ALIGNED_TYPE(t,x) typedef t ALIGNED_(x)

/*SOME USAGE SAMPLES*/

ALIGNED_TYPE_(double, 16) aligned_double_t;

ALIGNED_TYPE_(struct, CACHE_LINE) tagALIGNEDSTRUCT
{
    /*STRUCT MEMBERS GO HERE*/
}aligned_struct_t;

ALIGNED_TYPE_(union, CACHE_LINE) tagALIGNEDUNION
{
    /*UNION MEMBERS GO HERE*/

}aligned_union_t;

您可以使用以下代码进行测试(注意 #pragma pack --> 这是用于 MSVC)

You can test this with the following code (notice the #pragma pack --> This is for MSVC)

#if defined(_MSC_VER)
#define ALIGNED_(x) __declspec(align(x))
#else
#if defined(__GNUC__)
#define ALIGNED_(x) __attribute__ ((aligned(x)))
#endif
#endif

#define ALIGNED_TYPE_(t,x) typedef t ALIGNED_(x)

#pragma pack(1)
typedef struct tagSTRUCTPACKED
{
    int alignedInt;
    double alignedDouble;
    char alignedChar;
}struct_packed_t;
#pragma pack()

typedef struct tagSTRUCTNOALIGN
{
    int alignedInt;
    double alignedDouble;
    char alignedChar;
}struct_no_align_t;

typedef struct ALIGNED_(64) tagSTRUCTALIGNED64
{
    int alignedInt;
    double alignedDouble;
    char alignedChar;
}struct_aligned_64_t;


typedef struct tagSTRUCTWITHALIGNEDMEMBERS
{
    int ALIGNED_(8) alignedInt;
    double ALIGNED_(16) alignedDouble;
    char ALIGNED_(2) alignedChar;
}struct_with_aligned_members_t;

int main(int argc, char **argv)
{
    int i,j;
    struct_packed_t _packed;
    struct_no_align_t _noalign;
    struct_aligned_64_t _aligned64;
    struct_with_aligned_members_t _alignedmembers;

    char* names[] = {"_packed","_noalign","_aligned64","_alignedmembers"};
    char* ptrs[] = {(char*)&_packed,(char*)&_noalign,(char*)&_aligned64,(char*)&_alignedmembers};
    size_t sizes[] = {sizeof(_packed),sizeof(_noalign),sizeof(_aligned64),sizeof(_alignedmembers)};
    size_t alignments[] = {2,4,8,16,32,64};
    int alcount = sizeof(alignments)/sizeof(size_t);

    for(i = 0; i < 4; i++)
    {
        printf("Addrof %s: %x
", names[i], ptrs[i]);
        printf("Sizeof %s: %d
", names[i], sizes[i]);
        for(j = 0; j < alcount; j++)
            printf("Is %s aligned on %d bytes? %s
", 
                names[i], 
                alignments[j], 
                ((size_t)ptrs[i])%alignments[j] == 0 ? "YES" : "NO");
    }

    for(j = 0; j < alcount; j++)
    {
            printf("Is _alignedmember.alignedInt aligned on %d bytes? %s
", 
                    alignments[j], 
                    ((size_t)&_alignedmembers.alignedInt)%alignments[j] == 0 ? "YES" : "NO");
            printf("Is _alignedmember.alignedDouble aligned on %d bytes? %s
", 
                    alignments[j], 
                    ((size_t)&_alignedmembers.alignedDouble)%alignments[j] == 0 ? "YES" : "NO");
            printf("Is _alignedmember.alignedChar aligned on %d bytes? %s
", 
                    alignments[j], 
                    ((size_t)&_alignedmembers.alignedChar)%alignments[j] == 0 ? "YES" : "NO");
    }

    return 0;
}

希望这有帮助...

这篇关于跨平台 ALIGN(x) 宏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆