Struct nach Array casten: Risiko?

Gast #182195
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
> 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
> 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
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

Eine eigene Frage? Dieser Thread ist über 21 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.