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

Hallo!

Ich habe weniger ein Problem, eher eine Frage: Warum in diesem Programm

struct Data{
  int16_t x;
  int16_t y;
  uint8_t hp;
};
Data data;
void setup() {
  Serial.begin(115200);
  Serial.println(sizeof(Data));
  uint8_t* pointer = (uint8_t*)&data;
  for(byte i = 0;i < sizeof(Data);i++){
    if(!(pointer[i] >> 4)) Serial.print("0");
    Serial.print(pointer[i], HEX);
    Serial.print("\t");
  }
  Serial.println();
  data.x = 1000;
  data.y = 0x1234;
  data.hp = 100;
  for(byte i = 0;i < sizeof(Data);i++){
    if(!(pointer[i] >> 4)) Serial.print("0");
    Serial.print(pointer[i], HEX);
    Serial.print("\t");
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

, welches ich auf der Suche nach einer Möglichkeit, die Byte-Werte aus einer Instanz auszulesen, gibt an, dass sizeof(Data) 6 ist, dabei hat Data eine Größe von nur 5 Bytes. Klar, ich könnte einfach überall -1 rechnen, aber mir geht es darum, dass ich wissen will, warum das passiert. Außerdem würde das bedeuten, dass ich bei Arrays aus tausenden kleinen structs tausende Bytes verliere. Ich habe auch mal alle struct-Variablen gelöscht, wodurch die Größe ja 0 sein müsste, und sizeof(Data) ergab 1. Und ich habe es auch mit sizeof(data) probiert, da kam überall das Gleiche (Selbe?) raus. Weiß jemand von euch darüber mehr als ich?

Gruß
HTML-Fan

Auf welchem MC? Auf dem UNO sagt er 5.

Gruß Tommy

Also wenn ich dieses Programm auf einen Arduino UNO lade dann bekomme ich folgende Ausgabe:

5
00 00 00 00 00 
E8 03 34 12 64

Also sizeof(Data) ist 5.

Arduino IDE 1.8.12 (portable), Windows 10

Echt? Ich nutze den ESP32.

(deleted)

(deleted)

Die 6 kommt beim ESP8266 (Alignment auf 32 Bit Prozessoren)

Gruß Tommy

Edit:
Das gibt dort sogar 12 (auf UNO/MEGA 7):

struct Data{
  uint8_t hp;
  int32_t y;
  int16_t x;
};

Man kann hier nicht direkt 8 und 32 Bit Prozessoren vergleichen. Das hängt nämlich gerade mit der Speicherbreite/Wortgröße zusammen.

Eventuelle Lösung:
https://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Structure_002dPacking-Pragmas.html

Deshalb ergibt der Vergleich ja auch notwendigerweise ohne pack unterschiedliche Größen.

Gruß Tommy

Serenifly:
Eventuelle Lösung:
Structure-Packing Pragmas - Using the GNU Compiler Collection (GCC)

Prima,

#pragma pack(1)

löst das "Problem". Hat das irgendwelche Nachteile, macht das z.B. 2-Byte-Operationen einen Strich durch die Berechnung?

Der Speicherzugriff wird eventuell langsamer wenn die Datenstruktur über Speichergrenzen verteilt ist. Das hängt aber von der Prozessorarchitektur ab

Serenifly:
Das hängt aber von der Prozessorarchitektur ab

Wie ist das denn beim ESP32?

Nach meiner Meinung sollte man pack nur dann verwenden, wenn man Strukturen zwischen verschiedenen Architekturen austauschen will (z.B. ESP8266 <–> NANO). Sonst sollte man den Kompiler seine Optimierungsarbeit machen lassen.

Gruß Tommy

Tommy56:
Nach meiner Meinung sollte man pack nur dann verwenden, wenn man Strukturen zwischen verschiedenen Architekturen austauschen will (z.B. ESP8266 <–> NANO).

War nicht der Plan, ich wollte eher sowas wie Speicherplätze realisieren, die ein RAM-Abbild darstellen.

Tommy56:
Sonst sollte man den Kompiler seine Optimierungsarbeit machen lassen.

Gibt es die Möglichkeit, dass man nur bei bestimmten "struct"s Cycles gegen RAM tauscht?

Das pack kannst/solltest Du auf jedes struct einzeln anwenden.

Gruß Tommy

Dann so?

#pragma Data(1)

Nee, das gibt wieder 6 Bytes.

pack(n) kann man ja mehrmals verwenden oder auch mit pack() wieder die ursprüngliche Ausrichtung herstellen

Aha. Vielen Dank für die Infos, ich denke, dass ich erstmal bei schnellerem Zugriff bleibe, die FPS bei meinem Spiel fallen so schon gerne auf 25.

HTML-Fan:
Wie ist das denn beim ESP32?

[sub]6
00	00	00	00	00	00	
E8	03	34	12	64	00	[/sub]

Mit #pragma pack(1):

[sub]5
00	00	00	00	00	
E8	03	34	12	64	[/sub]