適用範囲:DS-5, RealView Development Suite (RVDS)
シナリオ
以下の単一のビットフィールドを含む構造体で仮定します:
struct bitfield { int m_offset:31; }data; char isSet() { return (data.m_offset != -1); }
Cプログラムを以下のようにビルドします:
armcc -c test.c
(最適化のレベルはデフォルトの
-O2
)
上記の結果は、以下のようなコードになります。(fromelf -c test.oを使って出力):
isSet 0x00000000: e3a00001 .... MOV r0,#1 0x00000004: e12fff1e ../. BX lr
data.m_offsetが-1と等しくないというテストは常に真(#1)となります。
これは、ビットフィールドがデフォルトでunsignedとして扱われるからです。
もしコードが次のように正の値に対してdata.m_offsetの値を比較するように変更されると:
char isSet2() { return (data.m_offset != 0x7fffffff); }
逆アセンブルの結果は、期待される次のようになります:
isSet2 0x00000008: e59f0010 .... LDR r0,[pc,#16] ; [0x20] = 0 0x0000000c: e3e01102 .... MVN r1,#0x80000000 0x00000010: e5900000 .... LDR r0,[r0,#0] 0x00000014: e1d10000 .... BICS r0,r1,r0 0x00000018: 13a00001 .... MOVNE r0,#1 0x0000001c: e12fff1e ../. BX lr $d 0x00000020: 00000000 .... DCD 0
回答
C Standardでは、型指定子がいずれかのintとしてビットフィールドの定義で使用されると、ビットフィールドがsignedまたはunsignedのいずれであるかは実装に依存します。
ARM Compiler toolchainでは、signedまたはunsignedの識別子のないプレーンなビットフィールド定義はunsignedとして扱われます。上の例では、int m_offset: 31 はデフォルトでunsigned intのビットフィールドとなります。
もし、signed intビットフィールドとして整数型ビットフィールドを扱う必要があるなら、2つの方法があります。
- signed識別子を使う
struct bitfield { signed int m_offset:31; };
- コンパイラオプション--signed_bitfieldsまたは--unsigned_bitfieldsを使ってビットフィールドの型をsigned intまたはunsigned intとして指定する。
詳細についてはCompiler Referenceを参照してください。