Forum: Compiler & IDEs Struct nach Array casten: Risiko?


von Philipp Sªsse (Gast)


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.

von OldBug (Gast)


Lesenswert?

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

von Chris (Gast)


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.

von Philipp Sªsse (Gast)


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!

von Rufus T. Firefly (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.