[gelöst] Warum ergibt sizeof(Data) immer ein Byte mehr?

Und gibt es dafür Programme?

Ja, brain Version 1.0 aber Vorsicht - oft gibt es nur die Betaversion 0.9 oder niedriger.

Gruß Tommy

Mir fällt gerade noch was ein - nach Größen ordnen reicht noch nicht. Wenn man

struct x{
  uint32_t a;
  uint16_t b;
};
struct y{
  x d;
  uint32_t c;
  uint16_t e;
};

, also alles nach Größe geordnet hat, dann ergibt das (ich lasse jetzt mal H und L weg)

0: a
1: a
2: a
3: a
4: b
5: b
6: -
7: -
8: c
9: c
A: c
B: c
C: e
D: e

, bei

struct x{
  uint32_t a;
  uint16_t b;
};
struct y{
  uint32_t c;
  x d;
  uint16_t e;
};

aber

0: c
1: c
2: c
3: c
4: a
5: a
6: a
7: a
8: b
9: b
A: e
B: e

, oder?

Schau Dir nochmal #32 an. Dein y ist nicht nach der Größe sortiert.

Es ist ja im Endeffekt:

  uint32_t a;
  uint16_t b;
  uint32_t c;
  uint16_t e;

Gruß Tommy

Es geht nicht darum dass nach der Größe zu sortieren sondern die Speichergrenzen zu berücksichtigen. Die Größe ist egal solange man 4 Byte große Blöcke hat

Ja und bei der angegebenen Reihenfolge hat man die für c halt nicht. Da wäre dann die andere Reihenfolge besser:

struct x{
  uint32_t a;
  uint16_t b;
};
struct y{
  x d;
  uint16_t e;
  uint32_t c;
};

Gruß Tommy

Hier wird's dann aber beknackt:

struct x{
  uint32_t a;
  uint16_t b;
  uint8_t c;
};
struct y{
  uint32_t d;
  x e;
  uint16_t f;
};

ergibt bei y

0: d
1: d
2: d
3: d
4: e.a
5: e.a
6: e.a
7: e.a
8: e.b
9: e.b
A: e.c
B: -
C: f
D: f

Bei struct y hat man dann

struct y{
  uint32_t d;

 [uint32_t e.a;
  uint16_t e.b;
  uint8_t e.c;]

  uint16_t f;
};

und da ist es unmöglich, alles richtig zu ordnen, da man ja nicht den struct so leicht zerpflücken und eine Variable dazwischenschieben kann. Gibt es echt nicht irgendeine Möglichkeit, mit der der Kompiler das zerlegt und ordnet? Da hilft nämlich nichtmal Brain 1.1 weiter.

Ich habe ja nicht behauptet, dass es immer möglich wäre ohne Ausrichtungs(füll)bytes auszukommen.
Man kann aber versuchen, Anordnungen zu wählen, die davon wenige brauchen. Um mehr geht es nicht.

Wie sollte der Kompiler etwas zerlegen und anders anordnen, was Du ihm anders vorgibst?

Gruß Tommy

Der Kompiler könnte

struct x{
  uint32_t a;
  uint16_t b;
  uint8_t c;
};
struct y{
  uint32_t d;
  x e;
  uint16_t f;
};

in

struct y{
  uint32_t d;
  uint32_t e.a;
  uint16_t e.b;
  uint8_t e.c;
  uint16_t f;
};

umformen und dann alles nach Größe ordnen, sodass

struct y{
  uint32_t d;
  uint32_t e.a;
  uint16_t e.b;
  uint16_t f;
  uint8_t e.c;
};

rauskommt. Da kann er sich, glaube ich, immer über die Entscheidung des Programmierers hinwegsetzen, denn der hat ja wahrscheinlich nichts gegen Optimierung. Schießlich optimieren Kompiler ja auchden Assembler-Code. Wenn das mal nicht der Fall sein sollte, könnte man sich doch ein schlaues Keyword wie "keep" oder so ausdenken und das setzt man einfach irgendwo in die Deklaration ein.

Darf er nicht, denn Du hast ihm mitgeteilt, dass Du auf e getrennt zugreifen willst. Deshalb muss e zusammen bleiben, weil Du es so gewollt hast.

Gruß Tommy

Wie kann ich ihm mitteilen, dass das nicht mein Plan ist?

Na, indem Du nicht struct x in struct y einfügst. Wenn Du das machst solltest Du ja dafür einen bestimmten Grund gehabt haben oder es war schlicht unüberlegt, wenn Du das überhaupt nicht wolltest.

Das kannst im Endeffekt nur Du wissen.

Gruß Tommy

Hatten wir doch schon in #pragma pack(1) mit seinen Nachteilen ...

Ein ESP32 mag nun mal 32 bit Grenzen lieber, und braucht auch sonst schonmal mehr RAM als ein 8bit Controller. (Schonmal sizeof(char*) ausprobiert?)

Was aber, wenn ich zwei verschidene Instanzen des Types x in dem Typ y haben will? Muss ich dann alles als Array benutzen oder die Variablen kopieren und ein wenig umbenennen? Ich dachte eigentlich, dass structs dafür da sind, dass man einerseits alle Variablen in einem Objekt zusammenfassen kann und andererseits ein struct als Parameter für eine Funktion mitgeben kann. Zum Beispiel arbeite ich momentan mit einem Musikprogramm mit Oszillatoren, bei denen immer zwei Oszillatoren mit einem struct zusammengefasst werden (struct RingOsc{Osc osc1, osc2; ...};), damit man diese zwei Oszillatoren untereinander verstimmen und Ringmodulieren kann. Ich bin ja ein großer Fan vom SID-Chip und das sollte sowas wie ein SID 2.0 werden. Müsste ich jetzt osc1 und osc2 durch die ganzen Variablen, aus denen Osc besteht, ersetzen?

Argh!
Ich habe mir doch glatt die Antwort selber gegeben: Man kann es als Parameter mitgeben, also muss es ein zusammenhängender Haufen sein! :confused::blush:

Oder mehrere Haufen in mehreren Parametern.

Gruß Tommy

Sei lieber froh, dass gelegentlich ein bool weniger als 32 bit braucht auf deinem ESP32 :slight_smile:

michael_x:
Sei lieber froh, dass gelegentlich ein bool weniger als 32 bit braucht auf deinem ESP32 :slight_smile:

Ich bin nicht in der Lage, meine extreme Begeisterung in Worte zu fassen.

@michael_x: Naja, man könnte ja 32 boolsche Werte in 32 Bit speichern :wink:
Das hast Du aber sicher nicht gemeint.

Gruß Tommy

Nach dem ich mir das durchgelesen habe ....

Du solltest dich mit dem Padding arrangieren.
Und nicht auf Byte komm raus optimieren.

Die Verwendung von uint8_t und seinen Brüdern ist auf 16, 32 und 64 Bit Maschinen sehr dicht an Unsinn, da meist mit erheblicher Rechenlast verbunden.

int , ist das natürliche Maß der Dinge (außer auf den 8 Bit Dingern)

Tipp:
Für ungenutzten Speicher, gibts kein Geld zurück.