Forum: PC-Programmierung C++, Pointer, direkte Adresse verwenden?


von abc x. (enybase)


Lesenswert?

Hallo,

Die Anweisung "int* ptr = 0x30000" funktioniert nicht.
Kann mir jemand sagen wie ich einem Pointer (in C/C++) eine Adresse 
dirket zuweise, ohne "ptr = &variable" zu benutzen? Ich habe nur den 
Adresswert, aber nicht "variable" zur Verfügung...

Danke.

von Karl H. (kbuchegg)


Lesenswert?

Im Zweifelsfall kann man in C und C++ den Compiler immer mit einem Cast 
zu etwas zwingen:

int* ptr = (int*)0x30000;

Man muss dann nur sselbst die Verantwortung dafür übernehmen, dass das 
eine sinnvolle Operation ist.

von Severino R. (severino)


Lesenswert?

Musst das Literal 0x30000 casten, da es ein int oder ein long ist:
Irgendwie so:
int* ptr = (int *)0x30000;

von Stefan Kunz (Gast)


Lesenswert?

Kommt drauf an in was für einer Umgebung dein Programm laufen soll.
Wenn es innerhalb eines Betriebssystemes läuft wird diese Zuweisung
zu einem Fehler führen. Speicherbereiche müssen erst in deine
Application reingemapt werden. Dies dient dem Schutz des 
Betriebssystemes
damit nicht "ausversehn" etwas an eine Stelle geschrieben wird, wo der 
Wert
nichts zu suchen hätte.

von P. S. (Gast)


Lesenswert?

Stefan Kunz wrote:

> Wenn es innerhalb eines Betriebssystemes läuft wird diese Zuweisung
> zu einem Fehler führen.

Nein.

von Stefan Kunz (Gast)


Lesenswert?

@Peter
Also eine kleine Erklärung könnte es schon sein. Vielleicht etwas zu 
verallgemeinert, aber Betriebssysteme, die eine MMU brauchen (QNX oder
Linux z.B.), müssen physicalischen Speicher erst in ihren virtuellen 
Speicherbereich mappen, damit darauf zugegriffen werden kann.
Somit sind solche Zuweisungen nur bedingt möglich, z.B. wenn das 
Zielsystem keine MMU besitzt.
MfG
Stefan Kunz

von P. S. (Gast)


Lesenswert?

"ptr" liegt im gueltigen Speicherbereich, worauf er zeigt/zeigen wird 
ist bei der Zuweisung irrelevant. In den hier gezeigten Beispielen 
findet keine Dereferenzierung dieses Pointers statt.

Auch sonst ist deine Erklaerung eher irrefuehrend, als hilfreich. Auch 
auf Systemen ohne MMU kann der Zugriff auf nicht existenden Speicher zu 
"Abstuerzen" fuehren. Und andersrum muss es auf Systemen mit MMU nicht 
zu "Abstuerzen" fuehren, das ist eine Frage der Implementation.

von Sven P. (Gast)


Lesenswert?

Es ist letztlich vollkommen wurscht, ob an '0x30000' irgendetwas 
Brauchbares zu finden ist. Es ist überdies auch vollkommen unbestimmt, 
wo '0x30000' im Speicher liegt.
C verlangt lediglich, dass ein Zeiger mittels irgendeiner Funktion auf 
eine Ganzzahl abgebildet werden kann, und dass diese (irgendeine) 
Funktion umkehrbar ist, man also von der Ganzzahl wieder zum korrekten 
Zeiger kommt.
Diese Ganzzahl muss überhaupt nichts mit Speicheradressen zu tun haben.

Wichtig könnte es sein, das Literal zu casten, damits passt, z.B. in der 
Art:
1
int *p = 0x30000UL;

Das gibt dann evtl. einen Typenfehler, den man mit dem (int *)-Cast 
erschlägt. Zulässig ist es an sich also, wenn diese (irgendeine) 
Funktion für 0x30000 definiert ist.

Die AVR-LIBC verschafft sich so z.B. auch Registerzugriff :-)

von Karl H. (kbuchegg)


Lesenswert?

Sven P. wrote:
> Es ist letztlich vollkommen wurscht, ob an '0x30000' irgendetwas
> Brauchbares zu finden ist.

<Nitpicking on>

Bei C bin ich mir da nicht sicher, da kenn ich den Standard zuwenig. 
Aber bei C++ hast du auch diese Garantie nicht. Theoretisch gibt es laut 
Standard die Möglichkeit, dass die Zuweisung eines beliebigen 
Zahlenwertes an einen Pointer undefined behaviour (das Schreckgespenst 
im Standard) auslöst.

Aus comp.lang.c-c++ weiß ich noch, das es wohl mal ein paar CPU gegeben 
hat, die für Adressen eigene Register hatten, und diese Register haben 
eine Exception ausgelöst, wenn ein ungültiger Wert in das Register 
geladen wurde (also kein Speicher an besagter Adresse lag). Wichtig: 
Allein schon das Laden des Wertes führte zur Exception, es musste noch 
nicht mal dereferenziert werden.

Persönlich erlebt hab ich das auch noch nie, kenns nur vom Hörensagen. 
Allerdings sind die Leute in comp.lang.c-c++ in der Beziehung 
zuverlässig (einige von denen arbeiten beim Standard mit)

<Nitpicking off>

von Sven P. (Gast)


Lesenswert?

K&R (zweite auflage, ANSI-C) sagt:
> Ein Zeigerwert darf in einen Integer-Typ umgewandelt werden, der für ihn
> groß genug ist; die nötige Größe ist implementierungsabhängig. Die
> Abbildungsfunktion ist ebenfalls implementierungsabhängig.

Es muss also nicht jede Ganzzahl unbedingt zu einem Zeiger 
korrespondieren, die Abbildungsfunktion könnte Lücken haben usw.

von Detlev T. (detlevt)


Lesenswert?

Hallo S. Meyer,

eigentlich jede Implementierung muss eine Möglichkeit bieten, auf 
Speicherbereiche an bestimmten Adressen zugreifen zu können, weil da zum 
Beispiel I/O-Bereiche eingeblendet werden.

Bei einem so wilden Typecast von int nach Zeiger garantiert einem aber 
niemand, dass es das tut, was man naiverweise erwartet. Besser wäre es 
wohl, eine entsprechende Variable mit fester Speicheradresse zu 
definieren, z.B. ein char-array, und die dann zu verwenden. Wie das 
genau geht verrät dir das Handbuch zu deinem Compiler.

Gruß, DetlevT

von Rolf Magnus (Gast)


Lesenswert?

> Besser wäre es wohl, eine entsprechende Variable mit fester
> Speicheradresse zu definieren, z.B. ein char-array, und die dann zu
> verwenden. Wie das genau geht verrät dir das Handbuch zu deinem
> Compiler.

Das hat auch den Vorteil, daß der Linker dann davon Kenntnis hat und 
nicht auf die Idee kommt, diesen Speicherbereich für was anderes zu 
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.