Cast eines Int zu Pointer

Gast #2770204
Lesenswert?

Hallo,

ich habe momentan eher eine Verständnisfrage als ein Problem, denn 
funktionieren tut mein Code.

Ich habe einen unsigned 32 Bit Integer. Woher dieser kommt ist 
nebensächlich. Zum Beispiel könnten die einzelnen Byte per USART 
übertragen werden.

Interessant ist eher die Interpretation dieses Zahlenwertes: ich nehme 
an es handelt sich um eine Adresse im Speicher und will sehen, was an 
dieser Stelle steht.
Dazu soll eine Funktion einen Pointer liefern, der auf diese Adresse 
zeigt.

Momentan schaut die Funktion so aus und funktioniert auch:
1
uint8_t *GetPointer(uint32_t addr)
2
{
3
  uint8_t *ptr;
4
  ptr = addr;
5
  return ptr;
6
}

Benutzt wird sie zB so:
1
uint32_t addr_int = 0xFFFF1234;
2
uint8_t *addr_ptr = GetPointer(addr_int);

Wie gesagt, funken tuts so.

Mich interessiert aber die Warnung, die der Compiler in der Zeile "ptr = 
addr;" ausgibt:
1
assignment makes pointer from integer without a cast

Ok, die Meldung ist noch verständlich. Füge ich einen Cast hinzu: "ptr = 
(uint8_t *) addr;" gibt er diese Meldung aus:
1
cast to pointer from integer of different size

Hier versteh ichs nicht mehr.
Ich sage dem Compiler, er soll die Zahl, die er in "addr" findet, als 
Adresse eines 8Bit Wertes interpretieren.
Wieso meckert er mir hier die Größe an? Die Größe eines Zeigers ist ja 
vom Adressbus abhängig, nicht von der Größe des Wertes, auf den er 
zeigt.
Beispiel: auf einer 16 Bit Maschine ist ein Zeiger auch dann 16Bit groß, 
wenn er auf ein "unsigned long long" zeigt.

Es handelt sich dabei übrigens momentan um einen 8 Bit AVR.
Ich speichere die Adresse dennoch als 32 Bit Int um
a) kompatibel zu bleiben zu anderen Prozessoren
b) im Map File der erzeugten Binärdatei werden die Adressen auch als 32 
Bit Wert angegeben. Das kommt wohl vom gcc, der eher für den PC Einsatz 
gedacht ist und führt zu Spiegelbildern im Speicher, die aber nicht 
stören.

Kann mir jemand erklären, wieso der Compiler meckert und wie ich casten 
sollte, um die Warning zu beseitigen?
Nochmal, mir gehts hier primär ums "Warum?", denn funktionieren tut 
alles...

Grüße,
Rudi
Moderator Persönliche Seite #2770216
Lesenswert?

Rudi schrieb:
> Ok, die Meldung ist noch verständlich. Füge ich einen Cast hinzu: "ptr =
> (uint8_t *) addr;" gibt er diese Meldung aus:
>
1
> cast to pointer from integer of different size
2
>

Ein Pointer hat auf einem AVR-8-Bitter die Größe von 2 Bytes, Du 
versuchst da aber, 4 Bytes (uint32_t) reinzuquetschen. Das heisst, 2 
Bytes gehen verloren. Offenbar sind diese beiden aber immer 0 bei Dir, 
deshalb scheint es dennoch zu funktionieren.
Gast #2770247
Lesenswert?

Danke, die Idee war gut, so ist er zufrieden:
1
ptr = ((uint8_t *)((uint16_t)addr));

Dachte nicht, dass der Compiler die Adressbusbreite des Targets so genau 
nimmt. Im Mapfile schreibt er zB auch "0x00800310                var".
Anscheinend gingen aber genau die unnötigen 2 Bytes verloren.
#2770254
Lesenswert?

Rudi schrieb:
> Danke, die Idee war gut, so ist er zufrieden:

Die Idee war nicht gut. Denn damit ist deine
'zukünftige Kompatibilität' und damit der Grund, warum du überhaupt in 
erster Linie einen uint32_t genommen hast, flöten gegangen.
D.h. als nächstes ist dieser uint32_t zu hinterfragen und der ganze 
Klapperatismus zumindest (da es keine saubere Lösung gibt) mittels 
Makros so zu verpacken, dass man ihn an geänderte Hardware durch das 
Anpassen von ein paar Makros adaptieren kann.

>
1
> ptr = ((uint8_t *)((uint16_t)addr));
2
>
>
> Dachte nicht, dass der Compiler die Adressbusbreite des Targets so genau
> nimmt.

Wenn du versuchst mit einem Autobus in eine PKW-Garage zu fahren, bist 
du heilfroh, wenn dich jemand davor warnt, dass da etwas schief gehen 
kann und Teiles deines Autobusses möglicherweise diese Aktion nicht 
überleben werden. Mit einem kleinen Autobus (mit 9 Sitzen) kommst du 
gerade noch so rein. Mit einem städtischen Autobus (mit 50 Sitzen) aber 
nicht mehr. Denn die sind meistens breiter.
Moderator Persönliche Seite #2770264
Lesenswert?

Karl Heinz Buchegger schrieb:
> Wenn du versuchst mit einem Autobus in eine PKW-Garage zu fahren, bist
> du heilfroh, wenn dich jemand davor warnt, dass da etwas schief gehen
> kann und Teiles deines Autobusses diese Aktion nicht überleben werden.

Karl Heinz, Deine Vergleiche sind immer herrlich!

Scheinbar "stirbt" nur die unnötige Blechverkleidung des Busses ;-)
#2770271
Lesenswert?

Frank M. schrieb:
> Karl Heinz Buchegger schrieb:
>> Wenn du versuchst mit einem Autobus in eine PKW-Garage zu fahren, bist
>> du heilfroh, wenn dich jemand davor warnt, dass da etwas schief gehen
>> kann und Teiles deines Autobusses diese Aktion nicht überleben werden.
>
> Karl Heinz, Deine Vergleiche sind immer herrlich!
>
> Scheinbar "stirbt" nur die unnötige Blechverkleidung des Busses ;-)

Die Aussenspiegel würde ich jetzt nicht unbedingt als unnötig ansehen 
:-)
Ist der Bus doppelt so breiten wie die Einfahrt dann hat man alles 
andere als ein bißchen kosmetischen Schaden :-)
Gast #2770321
Lesenswert?

Danke Karl-Heinz, du hast natürlich Recht. Kompatibel bin ich momentan 
mit dem gecaste nicht.

Frank M. schrieb:
> Fragt sich dann nur, warum Du einen uint32_t statt
> uint16_t dafür verschwendest.

Dazu muss ich weiter ausholen und dazusagen, dass ich eine Bibliothek 
verwende die definierte Schnittstellen vorraussetzt.
Und die Schnittstelle um die es hier geht ist eben als 32 Bit Int 
definiert.

Mir ist es deswegen überlassen, die geforderte Schnittstelle an die 
verwendete Hardware anzupassen.
Moderator Persönliche Seite #2770653
Lesenswert?

Rudi schrieb:
> Im Mapfile schreibt er zB auch "0x00800310                var".

Das ist aber eher eine Krücke.  Die ganze GNU-Toolchain kommt eigent-
lich schlecht bis gar nicht mit der beim AVR benutzten Harvard-
Architektur zurecht; die sind voll und ganz auf eine von-Neumann-
Architektur ausgerichtet, bei der alles an einem Adressbus hängt.

Um die Harvard-Busse des AVRs nun auf die von-Neumann-Idee der
Toolchain abzubilden, bekommen die einzelnen Busse Offsets.  Der
SRAM-Bus hat dabei den Offset 0x800000, sodass alle im RAM liegenden
Werte nach dem Linken als oberhalb 0x800000 dargestellt werden.
(IO registers liegen im gleichen Adressraum, unterhalb des SRAM.)

Werte von 0 bis < 0x800000 beziehen sich entsprechend auf den Flash-
Adressraum.
Gast #2770663
Lesenswert?

Rudi schrieb:
> Interessant ist eher die Interpretation dieses Zahlenwertes: ich nehme
> an es handelt sich um eine Adresse im Speicher und will sehen, was an
> dieser Stelle steht.

Der Vollständigkeit halber sei angemerkt, dass diese Annahme sehr 
grenzwertig ist :-)

Zeiger sind keine Adressen. Du siehst ja hier schon, wie übel das durch 
den Linker geht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren