Forum: Compiler & IDEs liegt mein Array "verkehrt herum" im Ram?


von Danny (Gast)


Lesenswert?

Hey Zusammen :)

Es ist spät, ich habe mir lang den Kopf zerbrochen und nun hoffe ich von 
Euch auf nen kleinen Tip :)

Ich habe ein Array data[8]. Dies ist gefüllt mit ( 0x01, 0x00, 0x0, 
0x50, 0x00, 0x00, 0x00, 0x00).
data[0] ist also 0x01, data[3] ist 0x50.

In einem Fall stellt data[0...3] den Inhalt eines uint32_t dar.

Mein Gedanke: Die Daten liegen ja im RAM hintereinander, sollte doch ein 
leichtes sein.

uint32_t test;
test = data[0];  ->> warn versucht, klappt natürlich nicht
test = (uint32_t){data[0]}; ->> auch nicht

uint32_t* ptr = data[0];
test = *prt   --> test wird mit (0x75, 0x01, 0x00, 0x00) geladen.

uint32_t* ptr = data[1];
test = *prt   --> test wird endlich mit (0x01, 0x00, 0x00, 0x50) 
geladen. Dann resetet der µC

uint32_t* ptr = &data[0];
test = *prt   --> test ist nun (0x50, 0x00, 0x00, 0x01) und ab diesem 
Moment bin ich total durcheinander... evt ist es auch einfach zu spät...

Aber evt habt Ihr nen Rat/Vorschlag für mich?

Danke und Gruß
Danny

von Paul (Gast)


Lesenswert?

de.wikipedia.org/wiki/Byte-Reihenfolge

von Yalu X. (yalu) (Moderator)


Lesenswert?

Integers werden auf dem von dir benutzten Prozessor little-endian, d.h.
beginnend mit dem niederwertigsten Byte im Speicher abgelegt. 0x01 wird
somit als das niedrigstwertige und 0x50 als das höchstwertige Byte
betrachtet, so das die gelesene uint32_t-Wert 0x50000001 ist.

von Bernd H. (Gast)


Lesenswert?

Vielen Dank für die schnellen Antworten!

Ich bin grad völlig verblüfft, bislang war für mich "big-endian" die 
einzig denkbarer Art und ich bin jahrelang damit in kein Problem 
gelaufen...

Das muss ich mir ausgeruht morgen früh nochmal selbst verdeutlichen :)

von DirkB (Gast)


Lesenswert?

1
uint32_t test;
2
test = *(uint32_t*)(&data[0]);

von Oliver S. (oliverso)


Lesenswert?

Danny schrieb im Beitrag #3367193:
> Ich bin grad völlig verblüfft, bislang war für mich "big-endian" die
> einzig denkbarer Art und ich bin jahrelang damit in kein Problem
> gelaufen...

Was für Exoten-Prozessoren hast du denn jahrelang benutzt?

Oliver

von klausr (Gast)


Lesenswert?

Oliver S. schrieb:
> Was für Exoten-Prozessoren hast du denn jahrelang benutzt?

Also, vor 20 Jahren war mal der Motorola 68000 (Atari, Amiga, Mac usw.) 
sehr populär (grad bei Assembler Programmierer). Der hatte Big-Endian.

von Ingo (Gast)


Lesenswert?

Warum benutzt du keine Union?

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Oliver S. schrieb:
> Was für Exoten-Prozessoren hast du denn jahrelang benutzt?

Sehr gebräuchliche Prozessoren mit Big Endian sind:

- 68000
- PowerPC
- SPARC

Viele ARM-Prozessorkerne lassen sich wahlweise als Big oder Little 
Endian konfigurieren, teilweise per externem Endianess-Pin. Beispiel 
Alcatel MTC-20285. Auch StrongARM- und Xscale-Prozessoren werden oft in 
Big Endian verwendet, gerade in Netzwerkkomponenten, da die Header von 
TCP/IP-Paketen auch in Big Endian (sog. Network Byte Order) spezifiziert 
sind.

Bei einigen MIPS-Prozessoren kann die Endianess sogar für jeden Prozess 
separat eingestellt werden, z.B. Toshiba TX39.

Nachtrag: Auch aktuelle ARM-Kerne beherrschen beide Betriebsarten, 
exemplarisch für den Cortex-A9:
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0407e/BABCIEHF.html

: Bearbeitet durch User
von Axel S. (a-za-z0-9)


Lesenswert?

DirkB schrieb:
1
> uint32_t test;
2
> test = *(uint32_t*)(&data[0]);

Weil noch keiner darauf eingegangen ist: DirkB hat hier völlig recht. 
Ganz unabhängig davon ob der TE einen kleinen oder großen Indianer 
programmiert, hat er auch Daten und Adressen durcheinandergewürfelt.

So hat er z.B. hier:

Danny schrieb:
> uint32_t* ptr = data[1];
> test = *prt

den Inhalt von data[1] (also vermutlich ein uint_8t) als Adresse 
eines uint32_t interpretiert. Und das geht in jedem Fall in die Hose. 
Wenn es das erwartete Ergebnis geliefert hat, dann auf jeden Fall nur 
zufällig.


XL

von Danny (Gast)


Lesenswert?

Mensch, da habe ich ja etwas losgetreten :)

Obwohl ich mir fest vornahm den Ziel-µC zu nennen, hab' ich's doch 
vergessen... Es ging/geht um einen Atmel AVR (Mega8 / Mega 128)...

Und tatsächlich hatte ich diese Probleme in den ganzen letzten Jahren 
nicht, aber meiner Recherche nach kann das auch gut sein, denn Probleme 
treten ja nur auf wenn Daten zwischen zwei Unterschiedlichen Systemen 
getauscht werden.
Auch dieses Mal wäre ich sicher nicht darüber gefallen, wenn ich mich 
nicht zu Testzwecken einmal als "fremdes System (big-endian-denkend)" 
eingemischt hätte :)


einmal noch für mein Verständnis Dirk's Lösung:

uint32_t test;
test = *(uint32_t*)(&data[0]);

mit (uint32_t*)(&data[0]); lade ich einen pointer auf einen uint32_t mit 
der Startadresse von data[0]. Durch den * vor dem ganzen wird der 
Ausdruck zum 32 Bit breiten Inhalt, auf den der Pointer zeigt. Um das 
big/little-endian muss ich mich dann zu Fuß kümmern.
Hab ich das soweit richtig verstanden?

Danke nochmal

von Danny (Gast)


Lesenswert?

vergessen:

Dirk's Lösung ist also mein letzter geschriebener Schritt

uint32_t test;
uint32_t* ptr = &data[0];
test = *prt

in einer Zeile, richtig?

von Ro B. (ro-ro)


Lesenswert?

Danny schrieb:
> uint32_t* ptr = &data[0];

Welchen Datentyps ist denn das Array jetzt?

von Danny (Gast)


Lesenswert?

achso sorry...

uint8_t

von Ro B. (ro-ro)


Lesenswert?

Danny schrieb:
> uint8_t

Dann wirst du wohl mindestens ein Warning bekommen. Und dann wird sich 
das ganze nicht so verhalten, wie du dir das (wahrscheinlich) 
vorstellst. Benutze doch einen Pointer vom selben Typ.

: Bearbeitet durch User
von Danny (Gast)


Lesenswert?

dann liest er aber kein 32bit-Wert aus 4 hintereinander liegenden 
8bit-Werten

von Ro B. (ro-ro)


Lesenswert?

Danny schrieb:
> dann liest er aber kein 32bit-Wert aus 4 hintereinander liegenden
> 8bit-Werten

Ah ja, mein Fehler. Klar, deshalb ja auch die Frage nach Endianess. 
Ziehe meinen Klugschiss zurück :)

von Ro B. (ro-ro)


Lesenswert?

Ro B. schrieb:
> Danny schrieb:
>> dann liest er aber kein 32bit-Wert aus 4 hintereinander liegenden
>> 8bit-Werten
>
> Ah ja, mein Fehler. Klar, deshalb ja auch die Frage nach Endianess.
> Ziehe meinen Klugschiss zurück :)

Würds dann aber eher sauber coden und dann shiften/adden. Oder siehst du 
deine Vorgehensweise als optimiert?

von DirkB (Gast)


Lesenswert?

Danny schrieb:
> in einer Zeile, richtig?

Ja.
Mehr wollte ich auch nicht machen.

Damit änderst du noch nichts an der Bytereihenfolge.

Wenn du zwischen verschiedenen Systemen die Werte austauschen willst, 
solltest du dir mal die Funktionen wie htonl oder ntohl ansehen.

von Danny (Gast)


Lesenswert?

@Dirk:  danke für den Tip, da werde ich mal vor dem schlafen gehen nach 
schauen :)

für den Moment habe ich mir geholfen, indem ich nicht die Bytes selbst 
"errechnet" habe sondern per (uint32_t[]){ 200 } eingefügt...

von Ro B. (ro-ro)


Lesenswert?

Sonst halt einfach das Array "rückwärts" benutzen.

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.