2016-10-08 5 views
0

Immer wenn Strukturen in andere Strukturen geworfen werden, bin ich aus irgendeinem Grund verwirrt. Ich schreibe einen Treiber für ein I2C-Gerät (2-Draht-Seriell-Schnittstelle) und verwende die Treiber des Herstellers als Referenz für die Erstellung meiner. Ich habe diese Union-Anweisung unten (die in einer Header-Datei definiert ist) und ich kann einfach ein paar Zeilen darin nicht verstehen. Nur ein kurzer Hintergrund, damit Sie wissen, was Sie sehen, ist das Haupt-Snippet unten, das diese TWI_statusReg-Variable einrichtet, die die Information von einem Statusregister jedes Mal hält, wenn ich Daten über den I2c-Bus sende/empfange. Dieses Datenregister ist 8 Bit lang und gehört zu einem Atmel Atmega328P Mikrocontroller. Hier sind meine Fragen ...Datenstruktur innerhalb einer Union (C-Programmierung)

1.) Es ist schwer, diese Frage in Worten zu formulieren, aber können Sie leicht erklären, warum Sie eine Datenstruktur in einer Union-Struktur wie diese deklarieren würden? Welche Schlüsselpunkte sollte ich herausgreifen?

2.) In der „.c“ Header-Definitionsdatei, die hier posten zu lang ist, gibt es eine einzige Zeile, das die folgenden

TWI_statusReg.all = 0; 

Ich weiß, es ist ein char-Variable im Header sagt Datei mit dem Namen "all", wie im Haupt-Code-Ausschnitt unten zu sehen ist. Ich verstehe jedoch nicht, was passiert, wenn eine Null zugewiesen wird. Werden alle Bits im Statusregister auf Null gesetzt?

3.) Die beiden Linien

unsigned char lastTransOK:1; 
unsigned char unusedBits:7; 

sind mir speziell verwirrend, was die Doppelpunkt-Operator tut.

Der Haupt Code-Snippet

/**************************************************************************** 
    Global definitions 
****************************************************************************/ 

union TWI_statusReg      // Status byte holding flags. 
{ 
    unsigned char all; 
    struct 
    { 
     unsigned char lastTransOK:1;  
     unsigned char unusedBits:7; 
    }; 
}; 

extern union TWI_statusReg TWI_statusReg; 
+0

Der Doppelpunkt-Operator gibt die Anzahl der Bits für dieses Feld an. –

+0

Und Bit-Felder sind nicht portabel. Es gibt keinen plattformunabhängigen Weg, den ich kenne, um zu wissen, welches Bit von "all" dem Bit "lastTansOK" entspricht. Es könnte das erste Bit sein, oder es könnte das letzte Bit sein. Und wenn Sie einen anderen Compiler verwenden, wird sich dies wahrscheinlich ändern. –

+2

Wenn 'TWI_statusReg.all = 0;' in einer Header-Datei ist (außerhalb einer 'Inline'-Funktion oder eines Makros, wirft dies ein sehr schlechtes Licht auf die Codequalität. Ihre Frage ist unklar und unklar. Am besten ist es, ein C zu bekommen Buch und lesen Sie die Abschnitte über 'struct's und' union's – Olaf

Antwort

0

1) Der Hauptgrund für eine solche Vereinigung zu schreiben ist Bequemlichkeit. Anstatt jedes Mal, wenn Sie auf bestimmte Bits zugreifen müssen, manuelle Bitmasken zu erstellen, haben Sie nun Aliase für diese Bits.

2) Durch Verbindungen können Sie auf Speicher verweisen, als ob seine Komponenten verschiedene Variablen wären, die unterschiedliche Typen darstellen. Gewerkschaften vergeben nur Platz für die größte Komponente in ihnen. Also, wenn Sie

union Example { 
     char bytes[3]; 
     uint32_t num; 
}; 

eine solche Vereinigung 4 Bytes würde nehmen müssen, da seine größte Art uint32_t dauert 4 Byte Speicherplatz. Es wäre wahrscheinlich mehr Sinn machen, eine Vereinigung wie dies obwohl zu haben, da Sie diesen Raum sowieso verwenden und es ist bequemer:

union Example { 
     char bytes[4]; 
     uint32_t num; 
}; 

Byte-Array lassen Sie einzelne Bytes von num zugreifen.

Ihre Vermutung ist richtig - Schreiben Wert für alle wird die entsprechenden Bits der Union setzen.

3) Dieses Konstrukt wird bit field genannt und ist eine Optimierung der Speichernutzung - wenn Sie eine Struktur von 2 Zeichen verwenden würden, würde es tatsächlich 2 Byte Speicherplatz benötigen, stattdessen wird ein Bitfeld deklariert Nehmen Sie nur 1 Byte (und Sie haben noch 6 weitere "unbenutzte" Bits)

Verwandte Themen