2017-04-25 16 views
2

構造内のメンバーのビット位置を取得するにはどうすればよいですか?例では構造内のメンバーのビット位置を取得する方法

>

typedef struct BitExamStruct_ 
{ 
    unsigned int v1: 3; 
    unsigned int v2: 4; 
    unsigned int v3: 5; 
    unsigned int v4: 6; 
} BitExamStruct; 

はGetBitPos(V2、BitExamStruct)のような任意のメンバーのビット位置を取得する任意のマクロがありますか?

私は、コンパイラが構造内のビット長に基づいてメンバーの位置を知っていると思っていました。だから私は、コードを実行せずに単純なマクロを使って取得できるかどうかを知りたい。

ありがとうございます。

+1

私は、メンバー変数の名前付けに混乱しています。 bit1、..、bit4はちょうど1ビットサイズか、あるいはbit1は3ビットサイズ、bit2は4ビットサイズ、bit3は5ビットサイズ、bit4は6ビットサイズであるはずですか? – rwols

+1

ご迷惑をおかけして申し訳ございません。それはちょうど名前です。 bit1は3ビット、bit2は4ビットです。そんな感じ。私はメンバーの名前を変更しました。 –

+1

私は[offsetof](http://en.cppreference.com/w/c/types/offsetof)があなたが探しているものだと信じています。 – rwols

答えて

2

私が知っている標準的な方法はありませんが、解決策が見つからないというわけではありません。

以下は、これまでに一番きれいなコードではありません。変数がメモリ内でどこから始まるかを特定するためのハックのようなものです。以下は、エンディアンに応じて、異なる結果を与えることができることに注意してください:

#include <stdio.h> 
#include <string.h> 

typedef struct s_toto 
{ 
    int a:2; 
    int b:3; 
    int c:3;  
} t_toto; 

int 
main() 
{ 
    t_toto toto; 
    unsigned char *c; 
    int bytes; 
    int bits; 

    memset(&toto, 0, sizeof(t_toto)); 
    toto.c = 1; 
    c = (unsigned char *)&toto; 
    for (bytes = 0; bytes < (int)sizeof(t_toto); bytes++) 
    { 
     if (*c) 
     break; 
    } 
    for (bits = 0; bits < 8; bits++) 
    { 
     if (*c & 0b10000000) 
     break; 
     *c = (*c << 1); 
    } 
    printf("position (bytes=%d, bits=%d): %d\n", bytes, bits, (bytes * 8) + bits); 
    return 0; 
} 

は私がやっていることは、私が0に全体の構造体を初期化し、私は私が見つけたい変数の値として1を設定することです。その結果、構造内で1ビットのみが1に設定されます。それから私はゼロでないものを見つけるまで、バイトあたりのメモリバイトを読みます。一度見つけられると、そのビットが見つかるまでそのビットを見ることができます。

+0

興味深い。 '0b10000000'表記はC言語の非標準的な拡張です(C++はそれを標準化しています)。はるかに重要なことに、この作業を行うためには 'toto.c'リファレンスを持たなければなりません。つまり、あなたは一般的に仕事をすることができません。あなたのコードは 'toto.c'で動作します。 'toto.b'または' toto.a'を設定するように改訂する必要があります。しかし、これは、標準よりも優れています。ビットフィールドは標準Cの最も難解な部分の1つであり、ほとんどの動作は実装定義です。 –

+0

'(bytes * 8)+ bits'はリトルエンディアンのバイトで、ビッグエンディアンのビットインデックスです。私はちょっとしたもののような一貫したエンディアンの番号付けを好むだろう。ボーナス '0b10000000' - >' 1' – chux

1

ポータブル(別名標準C)の方法はありません。あなたが完全にコントロールする必要があるか、この情報がひどく必要な場合は、ボックス外で考えてみると、ビットフィールドは間違ったアプローチです。適切な解決策はシフトとマスキングです。もちろん、これはあなたがソースコードを管理している場合にのみ実行可能です。

+0

あなたのコメントありがとうございました。このツールは私の会社のハードウェアレジスタのヘッダファイルを作成します。通常、私は本当に必要なビットフィールドのビット位置を定義します。しかし、毎回ハードウェア登録仕様。変更されると、それが起こります。 –

+0

おそらく、移植性は気にしないでしょうし、コンパイラのABIドキュメントでこの情報を見つけることができるかもしれません。 –

関連する問題