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?
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...
„ 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.
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.
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.
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.
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.
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.
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 :(