Forum: Mikrocontroller und Digitale Elektronik Pointer ist 3 Byte große?


von Stefan S. (stefanst)


Lesenswert?

Hallo!

Ich habe ein merkwürdiges Problem: Ich möchte gerne die Adresse eines 
Pointers (vom Pointer selbst) in einzelnen Bytes Speichern. Da das nicht 
auf anhieb funktioniert hat (das Zerlegen des Pointers), habe ich mal 
folgendes ausprobiert:
1
sizeof(char*);

Das liefert mir zu meinem Erstaunen den Wert 3!! Warum das denn? Ich 
nutze den An2131 von Cypress mit einem 8051-Kern. Das müsste doch 
eigentlich 2 zurückliefern, oder?

Viele Grüße,
Stefan

von Schneemann (Gast)


Lesenswert?

Ich bin zwar kein C-ler, aber könnte es sein, das die Function SizeOf() 
die string-beendende #0 mitzählt?

von Tom (Gast)


Lesenswert?

Pointer mit einem "string-beendenden #0", sehr, sehr interessant!

von (prx) A. K. (prx)


Lesenswert?

Für Maschinen mit getrennten Adressräumen existieren Compiler, die mit 
Pointern alle Adressen ansprechen können. Realisiert wird das, indem zur 
Adresse noch eine Adressraumkennung hinzugefügt und der Zugriff per 
Laufzeitfunktion abgewickelt wird. Das könnte hier der Fall sein. 
Möglicherweise ist dann per Option wählbar, ob das für alle Pointer 
gilt, oder nur für solcherart gekennzeichnete.

von rgf (Gast)


Lesenswert?

C war und ist schon immer krank! ;)

von H.J.Seifert (Gast)


Lesenswert?

Insbesondere beim 8051 ist das erforderlich, da es 
Adressüberschneidungen gibt. Der Pointer muss also ein Angabe enthalten, 
für welchen Speicher er gilt (data, idata, xdata, code), zumindest gilt 
das für den generic-Pointer.
Das 1.Byte des pointers stellt also den Typ dar, danach kommen 2 
Adress-Bytes. Kann allerdings bei anderen Compilern auch anders sein:-).

Wenn du den Speichertyp schon bei Deklaration angibst, hat er auch nur 2 
Byte, kann dann allerdings wirklich nur für diesen Speichertyp verwendet 
werden.

von Purzel H. (hacky)


Lesenswert?

Aha. Ein typisierter Pointer. Toll. Damit kann man das auf's RAM, auf's 
EEPROM und auf's Flash los ?

von Sven P. (Gast)


Lesenswert?

Das ist Abhängig von der Implementierung.

Ein Zeiger darf auch 1, 2, 4, 5, 6, 7, ... Bytes breit sein. Ein Zeiger 
muss noch nicht mal eine Zahl sein, er kann auch eine Struktur o.ä. 
sein.

von MaWin (Gast)


Lesenswert?

> Das müsste doch eigentlich 2 zurückliefern, oder ?

Nein.
Auch beim C166 sind's 3, bei manchen Mainframes auch 6.

Vermutlich ist der Cypress-Kompiler so flexibel,
dass er Zeiger in Code und Zeichen in (externes) RAM
unterschieden kann und braucht dafür 1 bit mehr als 16.

Manchmal kann man daran mit Compileroptionen drehen,
aber man sollte sich über die Konseqeunzen im klaren
sein, wenn Pointer nicht mehr unterschiedbar sind.

von Andreas R. (rebirama)


Lesenswert?

Jup ein Pointer mit Typisierung, geht für alles, erzeugt mehr Code und 
ist langsamer.
schau mal ins Manual deines Compilers, da sollte es drin stehen.

Ich kenns von sdcc:
generische pointer, wie in deinem fall haben 3 byte.
spezialisierte pointer, z.B. für xram haben nur 2 byte.
theoretisch könnte ein pointer für den data-,idata- oder pdata- bereich 
auch nur 8bit haben, ob das der sdcc kann, weiß ich allerdings gerade 
nicht.

Wie auch immer, wenn du spezielle pointer verwenden willst, muss du dir 
gedanken um dein memory-model machen und dein code muss auf das verdauen 
spezieller pointer ausgelegt sein.

von Stefan S. (stefanst)


Lesenswert?

Hey!
Danke erstmal für die vielen Antworten, jetzt ist mir die Sache auch 
klar geworden :D
Was ich aber komisch finde: Kann es sein, dass der 8051 eine Adresse 
"falsch herum" abspeichert? Wenn var0 an Adresse 0D60 sitzt und ich 
folgendes mache
1
var5 = (unsigned char) (&var0);
2
var6 = (unsigned char) (((int)(&var0))>>8);
3
var7 = (unsigned char) (((int)(&var0))>>16);
liefert mir das als Resultat

var5 = 60
var6 = 0D
var7 = 0

Gut, hier fällt mir schonmal auf, dass die 1, die dem Pointer auf Grund 
der Lage im XDATA-Bereich haben müsste, nicht enthalten ist...

Mache ich nun folgendes:
1
xdata long test _at_ 0x0D70;
2
test = &var0;
und lese nacheinander die Speicherzellen 0x0D70, 0x0D71, 0x0D72 aus (vom 
PC), so liefert mir das für
0x0D70: 0
0x0D71: 01
0x0D72: 0D
0x0D73: 60

Kann mir das jemand erläutern?

Viele Grüße,
Stefan

von Simon K. (simon) Benutzerseite


Lesenswert?


von (prx) A. K. (prx)


Lesenswert?

Stefan S. schrieb:

> var7 = (unsigned char) (((int)(&var0))>>16);

Wird immer 0 sein, weil "int" nur 16 Bits hat. Besser:

var7 = (unsigned char) (((long)(&var0))>>16);

von Peter D. (peda)


Lesenswert?

Stefan S. schrieb:
> Was ich aber komisch finde: Kann es sein, dass der 8051 eine Adresse
> "falsch herum" abspeichert?

Bei nem 8-Bitter gibt es kein "falsch herum". Egal, wie es der Compiler 
macht, es sind immer 2 Bytezugriffe erforderlich.


Peter

von Peter D. (peda)


Lesenswert?

Andreas R. schrieb:
> Wie auch immer, wenn du spezielle pointer verwenden willst, muss du dir
> gedanken um dein memory-model machen

Nö, das Memory Model gibt nur an, wo default Variablen abgelegt werden.

Deshalb sollte man das Large-Modell nur dann nehmen, wenn man wirklich 
triftige Gründe dafür hat. Default Variablen werden dann nämlich sehr 
langsam und erzeugen sehr viel Code.

In jedem Memory-Model kann man alle Memory-Specifier verwenden.
Pointer ohne Specifier sind immer 3 Byte groß (generic Pointer).


Peter

von Stefan S. (stefanst)


Lesenswert?

A. K. schrieb:
> Stefan S. schrieb:
>
>> var7 = (unsigned char) (((int)(&var0))>>16);
>
> Wird immer 0 sein, weil "int" nur 16 Bits hat. Besser:
>
> var7 = (unsigned char) (((long)(&var0))>>16);

Okay, das macht Sinn ;-) habs mal mit "long" statt "int" versucht, jetzt 
ist die 1 wieder da!

Nach dem, was ich im Netz gefunden habe, scheint der AN2131 mit dem 
8051-Kern also nach Big-Endian-Format sortiert...

Danke!

Viele Grüße,
Stefan

von Gast (Gast)


Lesenswert?

> ...  nach Big-Endian-Format sortiert...

Intel µCs haben immer little-endian.

Motorola, Renesas (H8) big-endian und SH sind meist umschaltbar.
Ist das nicht schön? :-)

von (prx) A. K. (prx)


Lesenswert?

Gast schrieb:

> Intel µCs haben immer little-endian.

Das ist hier nicht relevant, da der 8051 alle Pointer jenseits des 256 
Byte Primär-RAMs über DPTR nutzt. Daher kann der Programmierer das 
halten wie er will.

In diesem Fall könnte eine Rolle spielen, dass die Laufzeitfunktionen 
zuallererst auf das Tag-Byte zugreifen müssen, dies also sinnvollerweise 
an der ersten Stelle steht.

> Motorola, Renesas (H8) big-endian und SH sind meist umschaltbar.
> Ist das nicht schön? :-)

Noch schöner war NS32000. Big-endian bei Konstanten im Code und 
little-endian sonst. DEC hatte auch welche verbrochen, bei denen die 
Bytereihenfolge im Wort und die Wortreihenfolge im Doppelwort 
unterschiedlich war

von anonymous (Gast)


Lesenswert?

Der AN2131 ist nicht zwingend in einem festen Format sortiert. Die 
endianess der Variablen im Speicher bestimmt der Compiler.

Keil macht für den 8051 big endian.
sdcc little endian.

Genauso machen das die Hardwaredesigner mit den Peripheriemodulen,
dort können 16bit Register wiederum in beliebiger Reihefolge liegen.
hab mal das Datenblatt des AN2131 überflogen(den ich noch die verwendet 
habe).
Im USB-Teil sind einige 16bit register etc big-endian, andere wiederum 
little-endian.
Solange du auf die Register immer schön mittels der Namen der 
Einzelbytes zugreifst und sie von Hand "zusammenshiftest" ist alles in 
Butter.

von Gast (Gast)


Lesenswert?

>Die endianess der Variablen im Speicher bestimmt der Compiler.

Nee, nee. Bei 8-Bittern kann er das machen, aber sobald ein 16- oder 
32-Bitter eine int oder long-Variable speichert, legt die CPU (oder 
sogar das Businterface) die Anordnung fest.

von (prx) A. K. (prx)


Lesenswert?

Gast schrieb:

> Nee, nee. Bei 8-Bittern kann er das machen, aber sobald ein 16- oder
> 32-Bitter eine int oder long-Variable speichert, legt die CPU (oder
> sogar das Businterface) die Anordnung fest.

Klar doch, aber hier geht es eben um 8051, da legt die Maschine nichts 
fest und der Compiler hat die Wahl.

Auch bei vielen 8-Bit Prozessoren wird das durch 16-Bit Adressen im 
Speicher ebenfalls von der Maschine fest- oder nahegelegt, aber eben 
nicht bei 8051.

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.