Ohne jetzt drüber zu diskutieren das ich hier unaligned
Speicherzugriffen machen muss... Was passiert mit member3? Wenn ich
MEMBER_STRUCT getrennt von myStruct verwende wird vermutlich ein Byte
gepadded, da so ein Langwortzugriff möglich ist. Wir das padding Byte
bei member3 auch eingefügt, selbst wenn es eine "Unter-"Struct einer
packed Struct ist?
Danke und Gruß, Rainer
Rainer K. schrieb:> Ohne jetzt drüber zu diskutieren das ich hier unaligned> Speicherzugriffen machen muss... Was passiert mit member3? Wenn ich> MEMBER_STRUCT getrennt von myStruct verwende wird vermutlich ein Byte> gepadded, da so ein Langwortzugriff möglich ist. Wir das padding Byte> bei member3 auch eingefügt, selbst wenn es eine "Unter-"Struct einer> packed Struct ist?
Hmm
Gute Frage.
Der C-Standard hält sich bei derartigen Sachen sehr bedeckt. Ausser "Ja,
es kann Padding geben" ist da sehr wenig definiert.
Hast du schon versucht mittels sizeof zu Erkentnissen zu kommen, wie das
dein Compiler handhabt?
Habe den sizeof Test mal gemacht, ich hatte diesen vor geraumer Zeit
mit einer älteren GCC Version schon durchgeführt und ich bin mir sicher
das dort alle Padding-Bytes beseitigt wurden, auch bei Unterstrukturen.
Erstaunlicher Weise ist das bei meiner aktuellen Version 4.4.1 nicht der
Fall. In dem konkreten Beispiel wird member3 auf 4 Byte aufgeblasen.
Einmal öfter zeigt sich das man möglichst Compilerunabhänigen Code
schreiben sollte, dies ist aber in der Realität oft nur bedingt möglich.
:(
Danke für den Hinweis. :)
Ich würde mal sagen, dass das Padding von MEMBER_STRUCT durch das packed
auf myStruct nicht beinflusst wird und das so das einzige ist, was Sinn
macht. Was sollte sonst der Compiler bei einem Zugriff über Zeiger auf
MEMBER_STRUCT machen? Das kann ja nicht davon abhängen wo das
MEMBER_STRUCT liegt.
Ich seh grad, dass das auch explizit in der gcc-Dokumentation steht:
> In the following example `struct my_packed_struct''s members are> packed closely together, but the internal layout of its `s' member> is not packed--to do that, `struct my_unpacked_struct' would need> to be packed too.>> struct my_unpacked_struct> {> char c;> int i;> };>> struct _attribute_ ((_packed_)) my_packed_struct> {> char c;> int i;> struct my_unpacked_struct s;> };
Rainer K. schrieb:> Was passiert mit member3? Wenn ich MEMBER_STRUCT getrennt von> myStruct verwende wird vermutlich ein Byte gepadded, da so ein> Langwortzugriff möglich ist.
Das kommt auf die Architektur an. Hast Du eine spezielle im Sinn?
Andreas B. schrieb:> Ich würde mal sagen, dass das Padding von MEMBER_STRUCT durch das> packed auf myStruct nicht beinflusst wird und das so das einzige> ist, was Sinn macht.
Ist aber auch nicht so intuitiv. Du hast dann u.U. padding zwischen
einem Element der umgebenden packed Struktur und dem unpacked
Strukturelement. Zu wem gehört das Padding jetzt? Zur umgebenden
Struktur kann es nicht gehören, da diese per Definition kein Padding
enthalten kann. Zum unpacked Element kann es auch nicht gehören, da
sich dann sizeof(member) ändern würde.
Die richtige Antwort des Compilers ist diese:
1
"packed_structs.c", line 83: Error: #1032: Definition of nested
2
anonymous struct in packed "struct myStruct" must be __packed
>Zum unpacked Element kann es auch nicht gehören, da>sich dann sizeof(member) ändern würde.
Wieso "ändern"? Gegenüber welcher Referenzgröße?
sizeof(MEMBER_STRUCT) ist 4 wenn man es im normalen Kontext verwendet,
also gehört das pad-byte zu MEMBER_STRUCT, wo ist das Problem?
sebastians schrieb:>>Zum unpacked Element kann es auch nicht gehören, da>>sich dann sizeof(member) ändern würde.> Wieso "ändern"? Gegenüber welcher Referenzgröße?
Dem alleinstehenden MEMBER_STRUCT. sizeof(MEMBER_STRUCT) wäre dann
nicht mehr gleich sizeof(MYSTRUCT.member3).
> sizeof(MEMBER_STRUCT) ist 4 wenn man es im normalen Kontext verwendet,> also gehört das pad-byte zu MEMBER_STRUCT, wo ist das Problem?
Wenn man davon ausgeht, dass MEMBER_STRUCT ein abschließendes Padding
Byte enthält, "da so ein Langwortzugriff möglich ist", dann gelten
möglicherweise auch irgendwelche Einschränkungen bezüglich des
Alignments. Nehmen wir also mal an, das Alignment von MEMBER_STRUCT
wäre nicht beliebig (!=1). Dann hinge es vom Alignment der Elemente in
myStruct ab, ob Padding zwischen member2 und member3 eingefügt
wird. Die Anzahl der Padding Bytes müsste unter Umständen sogar für
verschiedene Instanzen von MYSTRUCT unterschiedlich sein, abhängig
davon, an welcher Adresse member2 tatsächlich liegt. Es sei denn, dass
Alignment von member3 bestimmt das Alignment von MYSTRUCT, was
wiederum dem Gedanken von packed widerspricht.
Gruß
Marcus
Hmm also GCC padded bei "nested structs", der KEIL Compiler aber sehr
wohl. Keiner von beiden gibt eine Warning oder gar error aus. Unschön
das es hier eine Diskrepanz gibt.
Und ganz intuitiv finde ich das Verhalten vom GCC nicht, denn ich dachte
eigentlich, das er bei einem typedef im grunde genommen die variablen
der inneren Struct (member3) quasi an die entsprechende Stelle kopiert,
quasi soetwas baut:
1
struct myStruct{
2
uint32_t member1;
3
uint8_t member2;
4
uint8_t one;
5
uint8_t two;
6
uint8_t three;
7
}__attribute__((__packed__));
8
typedef struct myStruct MYSTRUCT;
Sollte Member 3 noch tiefer durch typedefs verschachtelt sein, würde ich
erwarten das er soweit auflöst bis er auf die integralen Datentypen
kommt. Folglich hätte man nur noch (reell) eine Struktur die aus
integralen Datentypen besteht, wenn ich diese jetzt packed deklariere
gibt es kein Padding. Das würde ich intuitiv erwarten. GCC tut es nicht.
Danke an der Stelle an Andreas B. für das posten der Stelle aus der GCC
Doku. :)
Ich habe in Ansi-c Standard geschaut, da steht quasi nicht viel zu - es
wird quasi als Compiler dependent definiert.
Rainer K. schrieb:> Hmm also GCC padded bei "nested structs", der KEIL Compiler aber sehr> wohl.
?
> Keiner von beiden gibt eine Warning oder gar error aus.
Was ist denn "der KEIL Compiler"? Die von mir zitierte Fehlermeldung
stammt aus dem Keil MDK-ARM.
> Sollte Member 3 noch tiefer durch typedefs verschachtelt sein, würde ich> erwarten das er soweit auflöst bis er auf die integralen Datentypen> kommt. Folglich hätte man nur noch (reell) eine Struktur die aus> integralen Datentypen besteht, wenn ich diese jetzt packed deklariere> gibt es kein Padding. Das würde ich intuitiv erwarten.
Aber das kann doch gar nicht gehen. Member3 wäre dann nicht mehr
typkompatibel zu anderen Instanzen von MEMBER_STRUCT.
Gruß
Marcus
Rainer K. schrieb:> kommt. Folglich hätte man nur noch (reell) eine Struktur die aus> integralen Datentypen besteht, wenn ich diese jetzt packed deklariere> gibt es kein Padding. Das würde ich intuitiv erwarten.
Ich nicht.
Denn ich erwarte eigentlich, dass
korrekt funktioniert.
Das hinzufügen eines packed Attributes darf daran nichts ändern.
Schliesslich habe ich es immer mit der gleichen MEMBER_STRUCT zu tun.