11

不均一な場合にコンパイラを救済する方法はあります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 の値の量を追跡することは、かなりエラーが発生しやすく、1 時間後か何時間か後に「ああ、うまくいかない」と思う瞬間がかなりありました。くそー、定義する値の量を調整するのを忘れていました。

推奨される方法は sizeof 演算子を使用することですが、これはエラー チェックでは使用できないため、保持したいと考えています。

とにかく、sizeof 演算子を使用して U8BIT 値の量が偶数でなければならないという何らかの形式のエラー チェックを維持する方法はありますか?


LundinAaron McDaidによる複合ソリューション:

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

3 に答える 3

10

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);

ただし、特定の問題に対する実際の解決策は、構造体のパディングが有効になっていることを確認することです。その時、ズレが生じてはいけません。

于 2013-10-16T12:39:41.890 に答える
9

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);
}

が true の場合sizeof(e) % 2 == 1、ビットフィールドint:-!!(e)は禁止されている負のサイズになります。(イデオネ)

于 2013-10-16T12:34:20.927 に答える
5

これは、同じファイルで同じアサーション マクロを複数回使用できるバージョンです。

/*
    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]
于 2013-10-16T13:33:37.643 に答える