2016-04-07 7 views
6

Ich habe eine Registerdefinition vom Hersteller des Mikrocontrollers, die als ein Bitfeld behandelt werden kann. Das Register ist wie folgt definiert:Eine uint32-Variable in ein Bitfeld umwandeln - undefiniertes Verhalten?

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

Das Bitfeld Definition wie folgt aussieht:

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; 

Statt direkt an das Register zu schreiben, möchte ich zunächst eine Uint32 Puffervariable verwenden, aber immer noch sein kann es in der Art der Registerbitfelddefinition bearbeiten. Diese Implementierung scheint zu funktionieren, wie die Adresse nur mit & buffer_variable ersetzt:

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

könnte dies zu undefinierten Verhalten führen?

+0

Dies ist eine gute Frage. Meiner Meinung nach besteht die Möglichkeit darin, denselben Code auf zwei Architekturen zu testen, einem Big Endian, einem Little Endian. Ich habe solche Systeme hier und wenn es keine definitive Antwort gibt, werde ich etwas Code zusammenstellen, wenn ich Zeit habe. –

+1

@DavidHoelzer Das hat nicht viel mit Endianess zu tun. Sie können nicht wissen, wie ein Bit-Feld seine Bits ungeachtet der Endianess speichert. Das Verhalten von Bitfeldern ist anfangs nicht gut spezifiziert. [Siehe hierzu] (http://stackoverflow.com/questions/6043483/why-bit-endianness-is-an-issue-in-bitfields/6044223#6044223). – Lundin

+0

Ehrlich gesagt, benutze ich sie selten. Ich kann mir einfach vorstellen, dass die Endianz einen Einfluss haben könnte, wenn man sie auf etwas anderes wirft. –

Antwort

3

Ihre Puffervariable muss genau dem Typ eines der Union-Elemente entsprechen, in diesem Fall unsigned. Wenn der Compiler uint32 und unsigned als unterschiedliche Typen behandelt, führt dies zu undefiniertem Verhalten (verletzt strenge Aliasing-Regel). Andernfalls, wenn sie vom gleichen Typ sind, ist der Code in Ordnung.

(Als Randbemerkung, die meisten Fehler im Zusammenhang mit strengen Aliasing-Verletzungen werden durch den Optimierer des Compilers verursacht. Im Falle von flüchtigen Variablen ist dies weniger ein Problem, da der Compiler ist nicht erlaubt, sie trotzdem zu optimieren in der Praxis bezweifle ich, dass Sie jemals ein UB für dieses Szenario treffen, obwohl es in der Theorie UB sein könnte.)