web-dev-qa-db-ja.com

c-ビットフィールドのアドレスを取得できません

ビットフィールドのアドレスを取得できないのはなぜですか?

ビットフィールドへのポインタを作成するにはどうすればよいですか?

ここにコードがあります...

struct bitfield {
    unsigned int a: 1;
    unsigned int b: 1;
    unsigned int c: 1;
    unsigned int d: 1;
};

int main(void)
{
    struct bitfield pipe = {
        .a = 1, .b = 0,
        .c = 0, .d = 0
    };
    printf("%d %d %d %d\n", pipe.a,
            pipe.b, pipe.c, pipe.d);
    printf("%p\n", &pipe.a); /* OPPS HERE */
    // error: cannot take address of bit-field ...
    return 0;
}
16
sleepy_dog

ビットフィールドのメンバーは、(通常)ポインタで許可されている粒度よりも小さくなります。これはcharsの粒度です(ちなみに、charの-​​definitionによる)。少なくとも8ビットの長さである)。したがって、通常のポインタはそれをカットしません。

また、ビットフィールドメンバーへのポインタのタイプが何であるかは明確ではありません。そのようなメンバーを格納/取得するには、コンパイラはビットフィールドのどこにあるかを正確に知る必要があるためです(「通常の」ポインタタイプではできません)。そのような情報を運ぶ)。

最後に、それはほとんど要求された機能ではありません(ビットフィールドはそもそも頻繁に見られません)。ビットフィールドは、情報をコンパクトに格納したり、フラグのパック表現を構築したりするために使用されます(たとえば、ハードウェアポートへの書き込み)。単一フィールドへのポインタが必要になることはめったにありません-必要な場合は、いつでも通常のstructに頼って、最後の瞬間にビットフィールドに変換できます。

これらすべての理由から、標準では、ビットフィールドメンバーはアドレス指定できないとされています。 可能性がありますこれらの障害を克服することは可能です(たとえば、ビットフィールドメンバーにアクセスするために必要なすべての情報を格納する特別なポインタタイプを定義することによって)が、それは誰も使用しない言語のさらに別の複雑すぎる暗いコーナーになります。

31
Matteo Italia

アドレス可能な最小単位はバイトであるため、ビットフィールドのアドレスを持つことはできません(Cのバイトは必ずしも8ビット幅であるとは限らないことに注意してください)。

あなたが望むことができる最高のものは、それを含む構造のアドレスです。

(C11)標準の関連部分は、セクション6.5.3.2 Address and indirection operators(私のイタリック体)です。

単項&演算子のオペランドは、関数指定子、[]または単項*演算子の結果、またはオブジェクトを指定するlvalueのいずれかです。 notビットフィールドであり、レジスタストレージクラス指定子で宣言されていません。

最小のアドレス可能度がバイトであり、ビットファイルが次のように圧縮されている場合があります。

Addr\Bit   7   6   5   4   3   2   1   0
00001234 | a | b | c | d | ? | ? | ? | ? |
00001235 |   |   |   |   |   |   |   |   |

これらすべてのビットファイルのアドレスは実際には同じであることがわかるので、それほど有用ではありません。

ビットファイルを操作するには、実際には直接アクセスして、コンパイラに分類させる必要があります。ビット単位の演算子を使用しても、コンパイラがそれらをメモリにどのように配置しているかをknowしない限り、動作が保証されません。

7
paxdiablo

アドレスは整数のバイト数である必要がありますが、ビットフィールドは整数である必要はないため、 C標準で指定されています アドレス演算子&は一緒に使用できません。もちろん、ビットフィールドのアドレスを本当に処理したい場合は、ビット単位の演算を使用して、囲んでいる構造体のアドレスを使用できます。

5
1''

ビットフィールドのアドレスを出力することはできませんが、必要なサイズタイプ(1ビットメモリから2バイト(整数タイプサイズの場合はコンパイラに依存)メモリへの型キャスト)のローカル変数に割り当てることができます。アドレスを出力します。

unsigned int x = pipe.a; printf( "x =%d"、&x);

0
Sudarshana B C