ungenutztes Bitfeld (struct) mit 0 initialisiert oder undefiniert?

OP #7361211

Hallo zusammen,

gegeben sei folgender Code:

1
#include <stdio.h>
2

3
typdef struct myStruct {
4
    unsigned int a: 4;
5
    unsigned int : 4; // unbenanntes (ungenutztes) Bitfeld
6
    unsigned int b: 4;
7
}myStruct_t;
8

9
int main() {
10
    myStruct_t myVar = { .a = 2, .b = 3 }; // unbenanntes Bitfeld mit 0 initialisiert, andere Bitfelder mit expliziten Werten?
11
//...
12
}

Wird in diesem Beispiel das ungenutzte Bitfeld mit 0 initialisiert? Oder ist das undefiniert? Ich gehe mal davon aus, dass es undefiniert sein wird. Gibt es da eine Möglichkeit ohne Zwischenschritt (also ohne vorher das gesamte Struct mit 0 zu belegen und dann nochmal zuzuweisen) explizite Werte für die benannten Felder zu vergeben und automatisch alle ungenutzten Felder mit 0 zu initialisieren?

Danke und Grüße,

(Firma: Golden Delicious Computers)

gehe mal sicherheitshalber davon aus, dass es uninitialisiert ist. Nicht weil das eine spezielle Regel für bitfields wäre. Sondern weil myVar eine lokale Variable ist, also auf dem Stack liegt. Nur globale Variablen werden auf 0 vorinitialisiert (bzw. der gesamte Speicherbereich in dem sie liegen).

Aber: wie willst Du ein unbenanntes und ungenutztes Bitfield überhaupt abfragen, und wozu? Willst Du einen Zugriffs-Trick per *(int)&myVar machen? Probiere es mit printf("%08x", *(int)&myVar) aus...

Der C99-Standard schreibt in Abschnitt 6.7.8

„ 21 If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.“

Also wird dein nicht explizit initialisiertes struct Element mit 0 initialisiert.

Oliver

OP

Nikolaus S. schrieb:

gehe mal sicherheitshalber davon aus, dass es uninitialisiert ist. Nicht weil das eine spezielle Regel für bitfields wäre. Sondern weil myVar eine lokale Variable ist, also auf dem Stack liegt. Nur globale Variablen werden auf 0 vorinitialisiert (bzw. der gesamte Speicherbereich in dem sie liegen).

Aber: wie willst Du ein unbenanntes und ungenutztes Bitfield überhaupt abfragen, und wozu? Willst Du einen Zugriffs-Trick per *(int)&myVar machen? Probiere es mit printf("%08x", *(int)&myVar) aus...

Ich will Register eines Peripheriebausteines als typdef struct defnieren. Im Baustein gibt es Register, bei denen teilweise ungenutzte Bits vorkommen. Zwar ist es dem Baustein egal mit was man ihm an diesen Stellen im Register beschreibt, aber ich möchte das gerne definiert mit 0 schreiben.

Hier mal ein Beispiel für ein 8-bit register, bei dem 3 bits des Registers "reg" ungenutzt sind. Kann ich da sicherstellen, dass bei der Printf ausgabe immer "10" rauskommt? Ich habe den Code jetzt mal nicht auf einem Microcontroller laufen gehabt, sondern nur im C-Simulator. Da kommt immer 10 raus, was aber natürlich nichts heißen muss.

1
#include <stdio.h>
2
#include <stdint.h>
3

4

5
typedef struct reg
6
{
7
  uint8_t a:   3;
8
  uint8_t b:   1;
9
  uint8_t :   3;// - 3 bits im register sind unbenannt, da ungenutzt
10
  uint8_t c:   1;
11
} reg_t;
12

13
reg_t myBits = 
14
{
15
  .a = 2,
16
  .b = 1,
17
  .c = 0
18
};
19

20

21

22
int main()
23
{
24

25
    uint8_t myRegister = *(uint8_t*)&myBits;
26
    
27
    printf("%u", myRegister); // myRegister ist ein Byte, das normalerweise der Routine übergeben wird, die das dann zum Baustein per SPI sendet.
28

29
    return 0;
30
}
(Firma: Golden Delicious Computers)

Ja, so ähnlich habe ich das vermutet. Dann benenne das "unbenannte" Bitfield einfach (z.B. undefined1:3) und initialisiere es explizit. Wenn der Compiler gut ist, merkt er dass das gesamte struct definiert wird und macht nur einen Initialisierungsbefehl draus. Du kannst auch den Assemblercode anschauen was er daraus macht.

OP

Nikolaus S. schrieb:

Ja, so ähnlich habe ich das vermutet. Dann benenne das "unbenannte" Bitfield einfach (z.B. undefined1:3) und initialisiere es explizit. Wenn der Compiler gut ist, merkt er dass das gesamte struct definiert wird und macht nur einen Initialisierungsbefehl draus. Du kannst auch den Assemblercode anschauen was er daraus macht.

Okay danke! Ich war mir nicht sicher, ob es da irgendeine Möglichkeit direkt bei der Initialisierung gibt. Dann werde ich die entsprechenden Bitfelder einfach explizit mit Namen angeben und dann auf 0 setzen.

Nikolaus S. schrieb:

gehe mal sicherheitshalber davon aus, dass es uninitialisiert ist. Nicht weil das eine spezielle Regel für bitfields wäre. Sondern weil myVar eine lokale Variable ist, also auf dem Stack liegt. Nur globale Variablen werden auf 0 vorinitialisiert (bzw. der gesamte Speicherbereich in dem sie liegen).

Ist in dem Fall egal. Sobald ein einziges Element eines struct initialisiert wird, wird das ganze struct initialisiert, auch bei lokalen Variablen.

Oliver

Jonny O. schrieb:

Im Baustein gibt es Register, bei denen teilweise ungenutzte Bits vorkommen. Zwar ist es dem Baustein egal mit was man ihm an diesen Stellen im Register beschreibt, aber ich möchte das gerne definiert mit 0 schreiben.

Wenn du deiner C-Implementierung nicht traust, oder nur in so etwas ähnlichem wie C programmierst, das nichts mit dem C-Standard zu tun hat, dann gib dem unbenannten Element halt einen Namen, und weise dem die 0 explizit zu. Da ist ja nun wirklich kein Aufwand, und kann sogar noch erklärend kommentiert werden.

Obwohl, dem Baustein ist’s egal, der Compiler macht’s sowieso, da klingt das alles dann doch sehr nach - nun ja.

Oliver

Jonny O. schrieb:

uint8_t myRegister = (uint8_t)&myBits;

1
printf("%u", myRegister); // myRegister ist ein Byte, das

normalerweise der Routine übergeben wird, die das dann zum Baustein per SPI sendet.

Wenn es sowieso so eine Routine gibt, und die am Ende sowieso ein uint8_t braucht... dann könnte diese Routine das Problem mit einem einzigen & lösen. Nebenbei könnte man den cast in der Routine verstecken. Ich glaube, ich hab' die Frage nicht verstanden :(

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 3 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.