Struct nach Array casten: Risiko?

Gast #182195
Lesenswert?

Hallo,

ich habe eine Funktion, die Datenblöcke (von mir aus Block[16]) auf
eine  Speicherkarte wegschreibt. Wäre dann

WriteBlockToCard(Block);

Die nutze ich auch, um ein gleichlanges Struct wegzuschreiben, indem
ich sie z.B. mit

WriteBlockToCard(&ConfigStruct.Header);

aufrufe. Funktioniert einwandfrei, aber der gcc gibt mir immer eine
Warnung. Die bekomme ich natürlich mit

WriteBlockToCard((unsigned char*) &ConfigStruct.Header);

weg, aber ... hat die Warnung möglicherweise einen Sinn? Kann der gcc
z.B. nicht immer garantieren, daß das Struct zusammenhängend im
Speicher abgelegt wird? Oder daß die Reihenfolge erhalten bleibt?
(BigEndigan vs. LittleEndian-Probleme bei int im struct sind mir schon
bewußt.)

Dank und Gruß, Philipp.
Gast #182197
Lesenswert?

> weg, aber ... hat die Warnung möglicherweise einen Sinn? Kann der
> gcc z.B. nicht immer garantieren, daß das Struct zusammenhängend
> im Speicher abgelegt wird? Oder daß die Reihenfolge erhalten bleibt?

Beides wird AFAIK durch den C-Standard garantiert. Solange die
Deklaration der struct gleichbleibt, bleibt auch das Layout im Speicher
gleich.
Was der Compiler allerdings machen darf, sind Füllbytes einfügen. D.h.
sowas:
struct x { char x; int i; };

sizeof(x) könnte nun durchaus (mit 4-Byte-int) 8 Byte ergeben, da der
Compiler padding durchgeführt hat, um i auf eine durch 4 teilbare
Adresse zu legen.

Ob padding durchgeführt wurde, kannst du wie im Bsp. ganz leicht
überprüfen. Wenn sizeof(deine_struct) größer ist als die Summe der
enthaltenen Variablen, wurde es durchgeführt, sonst nicht. AFAIK ist es
unwahrscheinlich, dass der Compiler (bei gängigen structs) padding auf
einem Mikrocontroller nutzt.
Gast #182198
Lesenswert?

> ConfigStruct.Header ist tatsächlich eine weitere Struct in der
> ConfigStruct?

Nein, das erste Element, ein unsigned char. Damit habe ich also die
Startadresse des Struct, wenn es denn brav so angelegt wird.

> Beides wird AFAIK durch den C-Standard garantiert.

Das beruhigt mich, danke!

> Was der Compiler allerdings machen darf, sind Füllbytes einfügen.

Gut, daß Du mich erinnerst! Da der Code evtl. auch auf ARM portiert
wird, könnte das ein Thema werden.

Danke Euch!
Gast #182199
Lesenswert?

Ich würde eine solche Funktion dergestalt konstruieren, daß ein
void-Pointer auf den zu schreibenden Speicherblock verweist und als
zweites Argument die Anzahl der zu schreibenden Bytes übergeben wird -
dann lässt sich die Funktion legal mit allen Datentypen verwenden und
beim Aufruf muss halt mit dem sizeof-Operator oder anderen geeigneten
Mitteln die zu verwendende Größe bestimmt/festgelegt werden.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren