Home / ぼやきごと / 2012-05-31 / C++:ビットフィールドのアドレスは取得できない
C++:ビットフィールドのアドレスは取得できない

C++:ビットフィールドのアドレスは取得できない

一度でも試したことのある人やC/C++仕様を熟知している人なら既知だと思いますが、ビットフィールドのアドレスを取得することはできません。
つまりポインタや参照を取る関数の引数に渡すこともできません。

すべて開くすべて閉じる
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
-
!
 
 
-
|
|
!
 
 
-
|
|
|
!
// コンパイルエラーになるコードの例
#include <utility> // for swap
 
struct ByteData
{
    unsigned char low   : 4;
    unsigned char high  : 4;
};
 
int main(int, char**)
{
    ByteData data = { 1, 2 };
    std::swap(data.low, data.high); // エラー C2664
    return 0;
}

上記のようなコードを書くと、VC++2010などではコンパイルする以前にIntelliSenseに怒られます。*1
そしてもちろんコンパイルするとコンパイルエラーになります。

ちなみに、STLの std::bitset テンプレートクラスも値を1ビット単位で扱いますが、こちらはどうかというと…

すべて開くすべて閉じる
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 
 
 
 
-
|
|
|
|
!
#include <bitset>
#include <utility> // for swap
 
int main(int, char**)
{
    std::bitset<2> bits;
    bits[0] = 1;
    std::swap(bits[0], bits[1]);
    return 0;
}

何の問題も無くコンパイル&リンク成功して実行できます。

std::bitset<N> クラスの非const版 operator[] オーバロードはビットの参照を返すわけではなく、 std::bitset<N>::reference クラスの値を返します。
このクラスが std::bitset<N> インスタンスの特定ビットに対する操作を行うようになっています。
詳しくは bitset ヘッダを読みましょう。

例えば構造体定義のあるソースコードを解析して各メンバ値を別の構造体等へコンバートするコードを自動生成するような処理を作る場合にメンバの中にビットフィールドが含まれているとハマることがあるので気を付けましょう。
例がやけに具体的なのは気にしてはいけません。いけませんったら。

Category: [プログラミング][C++] - 2012-05-31 04:39:18

*1 VC++2010のIntelliSenseは問題ないコードでも怒ることがあったりしますが。