web-dev-qa-db-ja.com

コンパイル時にメモリ内のビットフィールドのレイアウトを検証する_Static_assertをGCC / GNU Cに書き込むことは可能ですか?

次の定義があるとします。

#include <stdbool.h>
#include <stdint.h>
#define ASSERT(cond) _Static_assert(cond, #cond)

typedef union {
    struct {
        bool bit0:1;
        bool bit1:1;
        bool bit2:1;
        bool bit3:1;
        bool bit4:1;
        bool bit5:1;
        bool bit6:1;
        bool bit7:1;
    };
    uint8_t bits;
} byte;

ASSERT(sizeof(byte) == sizeof(uint8_t));

次のようなコードを書くことは可能ですか?

#include <assert.h>
// ...
    assert(((byte) { .bit0 = 1 }).bits == 0b00000001);
    assert(((byte) { .bit1 = 1 }).bits == 0b00000010);
    assert(((byte) { .bit2 = 1 }).bits == 0b00000100);
    assert(((byte) { .bit3 = 1 }).bits == 0b00001000);
    assert(((byte) { .bit4 = 1 }).bits == 0b00010000);
    assert(((byte) { .bit5 = 1 }).bits == 0b00100000);
    assert(((byte) { .bit6 = 1 }).bits == 0b01000000);
    assert(((byte) { .bit7 = 1 }).bits == 0b10000000);
// ...

上記の条件が満たされない場合、コンパイル時エラーが発生しますか?

ASSERTマクロに条件を配置しようとすると、コンパイラーはexpression in static assertion is not constant、もちろんこれは完全に理にかなっています)

ソリューションでは、C言語のGNU拡張機能を使用できます。

8
Maciek Godek

問題の範囲内でひどくはありませんが、よりポータブルなソリューションを提供する可能性があります。

静的アサーションには式に制限があり、ユニオンから式を評価することはできません。

別の方法として、コードがメイクファイル(または同等のもの)によってビルドされると想定して、ビルドにステップを追加して条件を強制することを検討してください

static.verify: static_check.c
    cc -o static_check static_check.c
    ./static_check
    touch $@

    # Make the static.verify dependency for building objects/executable.
a.o: static.verify

基本的に、小さなプログラム 'static_check.c'を実行する必要があります。プログラムは、必要なエラーメッセージを生成できます。エラーを示すには、ゼロ以外の戻りステータスで終了する必要があります。

0
dash-o