时间结构大小检查,如果奇数出错

如果sizeof (struct Astruct)不均匀,是否有任何可能的方式让编译器sizeof (struct Astruct)出来?

背景信息:我们有一个16位微处理器,如果16位值不对齐,会导致处理器对齐错误。 在以下情况下可能会发生这种情况:

typedef struct
{
    U8BIT u8BitValue1;
    U8BIT u8BitValue2;
    U8BIT u8BitValue3;
} unevenAmountOf8BitValues;

typedef struct
{
    U16BIT u16BitValue1;
    U16BIT u16BitValue2;
} my16BitValues;

#define U8BIT_COUNT 3
#define U16BIT_COUNT 2

typedef struct
{
    unevenAmountOf8BitValues u8BitValues;
    my16BitValues u16BitValues;
} valuesCombined;

typedef union
{
    valuesCombined myValues;
    U8BIT buffer[sizeof(valuesCombined)];

    struct
    {
         U8BIT bufferU8[U8BIT_COUNT];
         U16BIT bufferU16[U16BIT_COUNT]; /* <<-- missalignment */
    } valuesPerType;
} myValuesInRamAndRom

我们现在要做的就是手动计算U8BIT / U16BIT / U32BIT值的数量(以及使用excel跟踪数量)并将其放入U(8/16/32)BIT_COUNT ,然后定义以下内容:

#if U8BIT_COUNT % 2 == 1
#error The number of U8BIT parameters need to be even, add a dummy
#endif

跟踪U8- / U16- / U32BIT值的数量是非常容易出错的,我们有很多时候我们都在想“嘿,它不工作”,一个小时或之后,哦! 该死,忘了调整数值的定义。

一个首选的方法是使用sizeof运算符,但不能用于错误检查,我真的很想保留它。

那么是否有使用sizeof运算符并保​​持某种形式的错误检查以确保U8BIT值的数量必须是偶数?


Lundin和Aaron McDaid的联合解决方案:

#define COMPILE_TIME_ASSERT(expr) {typedef U8BIT COMP_TIME_ASSERT[((!!(expr))*2-1)];}

使用C11编译器,请使用:

static_assert (sizeof(the struct) % 2 == 0,
               "Misaligned");

使用较老的编译器,你可以使用一些肮脏的技巧

#define COMPILE_TIME_ASSERT(expr) {typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0];}

...

COMPILE_TIME_ASSERT(sizeof(the_struct) % 2 == 0);

但是,针对您的特定问题的真正解决方案可能是确保启用了结构填充。 那么你不应该得到任何失调。


有可能,使用一种在Linux内核中也被使用的技巧:

#define BUILD_BUG_OR_ZERO(e) (sizeof(struct{ int:-!!(e);}))
#define ENSURE_EVEN_SIZE(e) BUILD_BUG_OR_ZERO(sizeof(e) % 2 == 1)

struct uneven{
  char a,b,c;
};

struct even{
  char a,b,c,d;
};

int main(){
  ENSURE_EVEN_SIZE(struct even);
  /* compiler error: */
  ENSURE_EVEN_SIZE(struct uneven);
}

如果sizeof(e) % 2 == 1为真,则位域int:-!!(e)将具有负尺寸,这是禁止的。 (Ideone)


这是允许在同一个文件中多次使用相同的断言宏的版本。

/*
    General purpose static assert.

    Works in/out -side of scope:
        STATIC_ASSERT(sizeof(long)==8);
        int main()
        {
            STATIC_ASSERT(sizeof(int)==4);
        }
*/
#define STATIC_ASSERT(X)            STATIC_ASSERT2(X,__LINE__)

/*
    These macros are required by STATIC_ASSERT to make token pasting work.
    Not really useful by themselves.
*/
#define STATIC_ASSERT2(X,L)         STATIC_ASSERT3(X,L)
#define STATIC_ASSERT3(X,L)         STATIC_ASSERT_MSG(X,at_line_##L)

/*
    Static assertion with special error message.
    Note: It depends on compiler whether message is visible or not!

    STATIC_ASSERT_MSG(sizeof(long)==8, long_is_not_eight_bytes);
*/
#define STATIC_ASSERT_MSG(COND,MSG) 
    typedef char static_assertion_##MSG[(!!(COND))*2-1]
链接地址: http://www.djcxy.com/p/73555.html

上一篇: time struct size check, error out if odd

下一篇: standard C (gcc specific features)?