使用C宏进行结构打包

时间:2013-07-12 18:23:29

标签: c gcc

我正在尝试通过#pragma pack实现_Pragma оperator指令,以创建用于数据结构对齐的宏。 所有这些都在书中的“C:In a Nutshell”

一书中有所描述。
#define  STR(s)  #s
#define  ALIGNMENT(n) _Pragma( STR (pack(n)) )
#define  ALIGNLEVEL(l) ALIGNMENT(l)
int  main()
{
   ....
    if(1)
    {
        ALIGNLEVEL(1)
        printf("%s\n", STR(Byte-aligned: no padding));>
    }
    else
    {
        ALIGNLEVEL(4)
        printf("%s\n", STR(four-byte: boundaries));

    }
    typedef struct s
    {
        size_t l_num;
        short  h_num;
        char ch;
    } s;

我期望的结果是我的结构的大小在x64位平台中等于 7字节(字节对齐)或 11字节。 上面的代码使用带有-Werror选项的 GCC 4.7.x 进行编译,返回结果为 8字节(32位OS)。

这个宏可能有什么问题?
为什么会这样?

1 个答案:

答案 0 :(得分:2)

您的程序是在假设pragma受if语句测试评估结果影响的情况下编写的。情况并非如此:第二个pragma只是覆盖第一个pragma,并且结构打包对齐无条件地设置为4.如果你注释掉第二个ALIGNLEVEL,你将得到预期的结果(用gcc 4.8测试。 1对ia32和x86-64)。

在查看固有的编译时编译指示时,编译器忽略运行时结构(例如if)是有道理的。即使您的if具有常量测试,也可以很容易地将其更改为非常量,并且编译器将无法提供一致的结果。如果在不同情况下需要不同的对齐方式,则必须使用预处理器:

#if SOME_CONDITION
    ALIGNLEVEL(1)
    printf("%s\n", STR(Byte-alligned: no padding));>
#else
    ALIGNLEVEL(4)
    printf("%s\n", STR(four-byte: boundaries));
#endif

如果需要根据运行时条件使用不同的对齐方式,则必须根据精心选择的抽象定义两种结构并在使用其中一种或另一种的代码之间切换。