Forum: Mikrocontroller und Digitale Elektronik Reihenfolge im struct und Reihenfolge im Speicher


von Struktur (Gast)


Lesenswert?

Hallo,

wie ich schon leidlich erfahren musste liegen die struct-Einträge nicht 
immer lückenlos nebeneinander, sondern es kann sein, dass der 
Prozessorarchitektur geschuldet nach einem boolschen Wert durchaus ein 
Freiraum entstehen kann, bevor der nächste Eintrag mit beispielsweise 
uint16_t gefunden wird.


Nun aber noch eine weitere Frage, gegeben ist folgendes struct:
1
typedef struct
2
{
3
  char Eintrag1[30];
4
  char Eintrag2 [50];
5
  char eintrag3 [20];
6
}MEINSTRCUT;


Liegt der Eintrag2 zwingend hinter dem Eintrag1 im Speicher?

von Ver Wirrter (Gast)


Lesenswert?

Warum ist hinter <Eintrag1> kein Blank, aber hinter
<Eintrag2> und <Eintrag3> schon?

Hat das einen tieferen Sinn?

von Ver Wirrter (Gast)


Lesenswert?

Typdefinitionen tut man nicht grossschreiben tun.
Das tut man nur bei Defines und Konstanten.
Tut man so! Isso bei anständigen Programmierern.

Ja gut, C ist geduldig, machen kann man alles.

von Axel S. (a-za-z0-9)


Lesenswert?

Struktur schrieb:
>
1
> typedef struct
2
> {
3
>   char Eintrag1[30];
4
>   char Eintrag2 [50];
5
>   char eintrag3 [20];
6
> }MEINSTRCUT;
7
>
>
>
> Liegt der Eintrag2 zwingend hinter dem Eintrag1 im Speicher?

Das hättest du mit minimalem Aufwand selber herausfinden können:

https://www.google.de/search?q=c+struct+memory+layout

gleich der erste Treffer beantwortet deine Frage:

https://stackoverflow.com/questions/2748995/c-struct-memory-layout

von M.A. S. (mse2)


Lesenswert?

Vielleicht auch interessant (bin gerade, angeregt durch diesen Thread, 
darauf gestossen, hab's aber noch nicht gelesen):

http://www.catb.org/esr/structure-packing/

von Dr. Sommer (Gast)


Lesenswert?

Struktur schrieb:
> nach einem boolschen Wert durchaus ein Freiraum entstehen kann, bevor
> der nächste Eintrag mit beispielsweise uint16_t gefunden wird.
>
> Nun aber noch eine weitere Frage, gegeben

Nicht nur nach bool Werten, sondern nach allen Datentypen. Die 
Reihenfolge ist aber so wie im Code vorgegeben.
Wozu ist das wichtig? Möchtest du den struct über eine Schnittstelle 
verschicken oder in eine Datei speichern und dabei ein bestimmtes Format 
erreichen (ohne Lücken)? Dann lies mal Serialisierung.

von Curby23523 N. (Gast)


Lesenswert?

Du kannst ein struct mit dem Attribut PACKED versehen (googlen für 
korrekte Anwendung). Dann werden die Variablen genauso im Speicher 
angelegt, wie du sie angibst, in genau der Reihenfolge ohne irgendwelche 
Lücken.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Curby23523 N. schrieb:
> Dann werden die variablen genazuso angelegt, wie du sie angibst, in
> genau der Reihenfolge ohne irgendwelche Lücken.

... unter Erkaufen eventueller drastischer Leistungseinbußen. Sollte man 
fairerweise erwähnen ;-)

von Dr. Sommer (Gast)


Lesenswert?

Curby23523 N. schrieb:
> Du kannst ein struct mit dem Attribut PACKED versehen

Dann werden aber u.U. alle Zugriffe auf die Variablen langsam, und wenn 
es tatsächlich um das Speichern/Verschicken geht löst das die diversen 
anderen Probleme nicht (Byte Order, Sign Format, Strict Aliasing)

von Curby23523 N. (Gast)


Lesenswert?

Danach hat der TO aber nicht gefragt. Mit "__attribute__((_packed_))" 
liegen die Variablen schön hintereinander.

von Dr. Sommer (Gast)


Lesenswert?

Curby23523 N. schrieb:
> Danach hat der TO aber nicht gefragt.

Wenn man jemandem ein Vorgehen empfiehlt, darf man ihn schon über die 
Probleme aufklären. Und das "packed" Attribut ist nur ein Trostpflaster 
auf einem vermutlich unangemessenen Vorgehen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Naja, man kann auch ein Symptom behandeln statt die Ursache. Und diese 
liegt höchstwahrscheinlich im Code des TOs begraben.

Frage an den TO: Warum soll das Programm von der Reihenfolge 
irgendwelcher Variablen im Speicher abhängig sein?

Ich sehe eigentlich keine Voraussetzung für so eine gravierende 
Bedingung.

: Bearbeitet durch Moderator
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Es dauert keine fünf Minuten, das mit einem simplen C-Compiler zu 
untersuchen:
1
#include <stdio.h>
2
3
typedef struct
4
{
5
  char Eintrag1[30];
6
  char Eintrag2 [50];
7
  char eintrag3 [20];
8
}MEINSTRCUT;
9
10
int main()
11
{
12
    MEINSTRCUT bla;
13
 
14
    printf("bla      %p\n", &bla);
15
16
    printf("Eintrag1 %p\n", &bla.Eintrag1);
17
    printf("Eintrag2 %p\n", &bla.Eintrag2);
18
    printf("eintrag3 %p\n", &bla.eintrag3);
19
20
    return 0;
21
}

Ergebnis laut https://www.onlinegdb.com/online_c_compiler
1
bla      0x7ffd68e65fc0                                                                                                      
2
Eintrag1 0x7ffd68e65fc0                                                                                                      
3
Eintrag2 0x7ffd68e65fde                                                                                                      
4
eintrag3 0x7ffd68e66010

Warum traut sich heutzutage niemand mehr, Vermutungen einfach 
auszuprobieren?

von Dr. Sommer (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Warum traut sich heutzutage niemand mehr, Vermutungen einfach
> auszuprobieren?

Nur weil in C(++) etwas bei einem Versuch funktioniert, heißt das noch 
lange nicht dass es korrekt im Sinne des Standards ist, und daher unter 
allen Bedingungen funktioniert. Gerade solche Dinge wie Speicher-Layouts 
sind da ein gefährliches Pflaster.

von Halb Blinder (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Warum traut sich heutzutage niemand mehr, Vermutungen einfach
> auszuprobieren?

Die Ergebnisse eines Compilers (oder auch mehrerer) reicht
ja nicht aus um eine allgemein gültige Aussage zu liefern.

Erst wenn man alle Compiler auf der Welt danach ausgetestet hätte ....

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ich bin mir nicht sicher, ob der Threadstarter eine allgemeingültige 
Aussage, die für alle Compiler, Prozessorarchitekturen und Wetterlagen 
dieses Universums gilt, oder ob er vielleicht auch nur eine vage 
Vorstellung davon gewinnen möchte, wie Objekte im Speicher angeordnet 
werden.

Struktur schrieb:
> Liegt der Eintrag2 zwingend hinter dem Eintrag1 im Speicher?

Diese Frage kann sich nämlich auch auf die Reihenfolge beziehen. Ginge 
es nur ums Alignment, hätte die Frage anders gelautet, denn der 
Threadstarter hat durchaus verstanden, daß es eine entsprechende 
Ausrichtung von Strukturelementen geben kann.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Rufus Τ. F. schrieb:
> Diese Frage kann sich nämlich auch auf die Reihenfolge beziehen.

Ich abe es auch so verstanden, dass die Frage ausschließlich die 
Reihenfolge betraf. Der TO schrieb auch im Eingangsbeitrag:

"dass der Prozessorarchitektur geschuldet nach einem boolschen Wert 
durchaus ein Freiraum entstehen kann, bevor der nächste Eintrag mit 
beispielsweise uint16_t gefunden wird."

Über die Lücken wusste er also Bescheid.

Und wenn er Google nach "C struct order" angeworfen hätte, dann hätte 
ihm bereits der erste Eintrag geholfen:

https://stackoverflow.com/questions/2748995/c-struct-memory-layout?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

--------------------
C99 §6.7.2.1:

12 Each non-bit-field member of a structure or union object is aligned 
in an implementation- defined manner appropriate to its type.

13 Within a structure object, the non-bit-field members and the units in 
which bit-fields reside have addresses that increase in the order in 
which they are declared. A pointer to a structure object, suitably 
converted, points to its initial member (or if that member is a 
bit-field, then to the unit in which it resides), and vice versa. There 
may be unnamed padding within a structure object, but not at its 
beginning.
--------------------

Die Reihenfolge ist in C also garantiert - abweichend zu anderen 
Programmiersprachen wie z.B. C#.

Ich selbst würde aber niemals Annahmen über Positionen in einer struct 
machen, denn es gibt immer eine portable Lösung.

von Sebastian S. (amateur)


Lesenswert?

Ich weiß gar nicht ob das heute überhaupt noch nötig ist. Soweit mir 
bekannt packen die Compiler die Daten in der - für den Rechner - 
"natürlichen" Anordnung.
Hat man also einen 16 Bit Rechner, so werden, falls möglich, 
char-Variablen immer an Wort-Grenzen abgelegt. So ist der Zugriff zwar 
schneller, aber die Speicherausnutzung schlechter. Seit dem es dieses 
Verhalten gibt, gibt es auch das Schlüsselwort "packed".

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Sebastian S. schrieb:
> Hat man also einen 16 Bit Rechner, so werden, falls möglich,
> char-Variablen immer an Wort-Grenzen abgelegt.
Bei char-Variablen eben nicht, aber alles was >= 2 Byte groß ist.

Sebastian S. schrieb:
> Seit dem es dieses
> Verhalten gibt, gibt es auch das Schlüsselwort "packed".
Das ist GCC-Spezifisch und nicht portabel...

von dummschwaetzer (Gast)


Lesenswert?

Sollte in der Manual des Compilers für die jeweilige Zielplattform 
erwähnt sein.

von dummschwaetzer (Gast)


Lesenswert?

z.B. MSP CodeCoposer 16.9 Kapitel 6.2.1 Data Type Storage

struct

Members are stored as their individual types require.

Multiple of 8 bits aligned to boundary of largest member type; members 
are stored and aligned as their individual types require.

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.