17

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

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

これがコードです...

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

5 に答える 5

36

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

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

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

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

于 2012-11-25T01:17:57.003 に答える
8

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

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

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

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

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

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

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

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

于 2012-11-25T01:13:59.403 に答える
5

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

于 2012-11-25T01:15:43.540 に答える
-1

同様に、個々のバイトをアドレス指定するだけの場合は、次のようにすることができます。

union PAIR  {
    struct { uint8_t l, h; } b;
    uint16_t w;
};

PAIR ax;

&ax.w、&ax.bl、&ax.bh などの部分へのポインターにアクセスできるようになりました。ただし、これはまだ個々のビットを指すことができないことに注意してください。これについては以前の説明を参照してください。

編集:固定例

于 2015-07-07T13:31:16.303 に答える