2016-04-07 8 views
6

私はビットフィールドとして扱うことができるマイクロコントローラの製造元が提供するレジスタ定義を持っています。uint32変数をビットフィールドにキャスト - 未定義のビヘイビア?

#define SCU_WDTSCON0 (*(SCU_WDTSCON0_type *) 0xf00360f0u) 

ビットフィールドの定義は次のようになります:レジスタは、次のように定義されて

typedef volatile union { 
unsigned U; 
int I; 
struct { 
    unsigned ENDINIT :1; // [0:0] End-of-Initialization Control Bit 
    unsigned LCK :1; // [1:1] Lock Bit to Control Access to WDTxCON0 
    unsigned HPW0  :2; // [3:2] Hardware Password 0 
    unsigned HPW1  :4; // [7:4] Hardware Password 1 
    unsigned PW :8; // [15:8] User-Definable Password Field for Access to WDTxCON0 
    unsigned REL :16; // [31:16] Reload Value for the WDT 
    } B; 
} SCU_WDTSCON0_type; 

代わりの直接のレジスタへの書き込み

は、私が最初にUINT32バッファ変数を使用したいが、それでも可能レジスタビットフィールド定義の方法でそれを編集することができる。

volatile uint32 buffer_variable; 
SCU_WDTSCON0_type register_buffer = (*(SCU_WDTSCON0_type *) &buffer_variable); 

でした。このリード未定義の動作に: この実装はアドレスだけで& buffer_variableに置き換えられて、動作しているようですか?

+0

これは良い質問です。私の考えでは、テストする方法は同じコードを2つのアーキテクチャ、1つのビッグエンディアン、1つのリトルエンディアンで試してみることです。私はこのようなシステムをここに持っています。決定的な回答がなければ、時間があるときにコードをコンパイルします。 –

+1

@DavidHoelzerこれは、エンディアンとはあまり関係ありません。ビットフィールドがエンディアンに関係なくビットをどのように格納するかを知ることはできません。ビットフィールドの振る舞いは、あまり指定されていません。 [これを参照してください](http://stackoverflow.com/questions/6043483/why-bit-endianness-is-an-issue-in-bitfields/6044223#6044223)。 – Lundin

+0

正直なところ、私はほとんどそれらを使用していません。エンディングが他のものにキャストされるとエンディングが影響を与える可能性があると私は想像することができます。 –

答えて

3

バッファ変数は、ユニオンメンバーの1つ(この場合はunsigned)とまったく同じ型である必要があります。コンパイラがuint32unsignedを異なる型として扱うと、未定義の動作になります(厳密なエイリアシング規則に違反します)。それ以外の場合は、同じ種類のコードは正常です。

(コンパイラのオプティマイザが厳密なエイリアシング違反に関連するほとんどのバグは、コンパイラのオプティマイザによって発生するため、コンパイラはこれらを最適化することができないため、揮発性変数の場合は問題になりません。実際には、たとえそれが理論的にはUBになる可能性があるとしても、このシナリオではUBに遭遇することはないだろう)。