Kann ein Zeiger jemals auf sich selbst zeigen?

Lesezeit: 9 Minuten

Benutzeravatar von Lazer
Laser

Meine Frage ist: Wenn eine Zeigervariable dieselbe Adresse wie ihr Wert hat, zeigt sie dann wirklich auf sich selbst?

Zum Beispiel – im folgenden Codestück ist a ein Zeiger auf sich selbst?

#include<stdio.h>

int main(){
   int* a;
   int b = (int)&a;
   a = b;
   printf("address of a = %d\n", &a);
   printf("  value of a = %d\n", a);
}

Wenn a kein Zeiger auf sich selbst ist, dann stellt sich wieder dieselbe Frage: Kann ein Zeiger auf sich selbst zeigen?

Wie ist ein selbstzeigender Zeiger nützlich?

  • ppl, warum die negvotes? zu einfach für dich??

    – Laser

    28. März 2010 um 6:43 Uhr

  • Mein Frage ist… — ein “Zweifel” ist etwas ganz anderes.

    – Äther

    28. März 2010 um 18:07 Uhr

  • Obwohl es legal ist, frage ich mich, was der Compiler tatsächlich tut, wenn er auf so etwas stößt. Da der Compiler selbst einige Optimierungen vornimmt, würde ich wetten, dass er sie herausnimmt. Aber ich konnte es nicht mit Sicherheit sagen.

    – Natalie Adams

    28. März 2010 um 20:40 Uhr

  • Hier ist ein Link zu dieser Frage: stackoverflow.com/questions/2532102/…

    – Änd

    12. März 2015 um 20:59 Uhr

  • @amdn Was Sie brauchen, ist ein Verweis auf Ihren eigenen Kommentar.

    – mbomb007

    1. März 2018 um 14:24 Uhr


void* p = &p;

Es ist nicht sehr nützlich, aber Strukturen, die auf sich selbst zeigen, sind in kreisförmigen Listen der Länge 1 nützlich:

typedef struct A {
  struct A* next;
} A;

A a = { &a };

Ich glaube, Sie meinten anhand Ihres genauen Beispiels:

int* a;
int b = (int)&a;
a = (int*)b;

// which can be simplified to:
int* a = (int*)&a;

  • Beachten Sie, dass sich das, was Sie mit der Struktur gemacht haben, von dem unterscheidet, was er zu tun versuchte. Ein Zeiger, der auf sich selbst zeigt, unterscheidet sich deutlich von einer Struktur, die einen Zeiger auf sich selbst hat. +1 für das Beispiel, da dies wahrscheinlich das ist, woran er bei selbstreferenziellen Zeigern denken sollte.

    – Phil

    28. März 2010 um 6:53 Uhr

  • @Phil: Es ist konzeptionell anders, daher kommt der ganze Nutzen, aber beachten Sie, dass A::next auf sich selbst zeigt, da es das erste Mitglied der Struktur ist &a == &a.next.

    Roger Pate

    28. März 2010 um 14:44 Uhr


  • Das erste Beispiel ist in der Tat nützlich: Es erstellt zur Kompilierzeit einen eindeutigen Zeigerwert, der nützlich sein kann, um bestimmte Objekte zu markieren oder einige Informationen zu übermitteln, die sonst in manchen Situationen nicht möglich sind (z. B. nicht modifizierbare APIs). Aber für diese Definition des Zeigers allein würde es reichen … die Zuweisung erspart einem nur die Verwendung & zusätzlich 🙂

    – stefankt

    9. Mai 2016 um 23:35 Uhr

Benutzeravatar der Cam
Nocken

Was Sie dort eigentlich tun, ist nicht mit dem Zeiger auf sich selbst zeigen. Sie sind Verwenden des für den Zeiger zugewiesenen Speicherplatzes zum Speichern des Ortes des Zeigers. Ein Zeiger auf int zeigt auf ints – niemals auf andere Zeiger auf ints, einschließlich sich selbst.

Angenommen, Sie erstellen einen Zeiger a:

int * a;

Es bekommt seinen eigenen Platz im Gedächtnis:

   4     a (5)    6
[....][00000000][....]

Nehmen wir in diesem einfachen Beispiel an, dass sich a am Speicherplatz „5“ befindet.

Wenn Sie dies tun würden:

a = (int*)&a;

… würde folgendes passieren:

   4     a (5)    6
[....][00000005][....]

Was hier passiert, ist das a zeigt auf das, was es für eine Ganzzahl an Position 5 hält. Dies ist auch derselbe Speicherort wie &a zeigt, aber im Kontext von was a zeigt, zeigt es jetzt auf die Ganzzahl an Position 5 – und diese Ganzzahl ist 5.

Zum Beispiel würde beides funktionieren:

cout<<(int)a;//outputs 5
cout<<*a;//Outputs the integer at memory location 5 - which is 5.

Wenn Sie einen Zeiger auf a erstellen möchten, können Sie dies auf jeden Fall tun – auf eine der folgenden Arten:

int **b = (int**)a;

oder

int ** b = &a;

Aber es ist sehr wichtig, das zu erkennen a ist kein Zeiger auf sich selbst. Es ist ein Hinweis auf die Ganzzahl an der Stelle, an der sie gespeichert ist – was zufällig derselbe ist wie sein eigener Standort.


Um weiter zu zeigen (durch ein noch einfacheres Beispiel), was vor sich geht, könnte etwas Ähnliches mit an passieren int. Das heißt, Sie können den Speicherplatz einer speichern int in sich:

int a=999;

a hat jetzt einen Speicherort und einen Wert von 999 (wir nehmen an, dass es an dem Speicherort ’46’ abgelegt wurde):

  45     a (46)   47
[....][00000999][....]

Sie befindet sich an der Stelle „46“ – wenn wir wollten, könnten wir diese Zahl als ganze Zahl darin speichern a:

a=(int)&a;

  45     a (46)   47
[....][00000046][....]

und nun a ist gleich &a im Wert, aber nicht im Typa nur eine Ganzzahl ist, zeigt es jetzt nicht mehr magisch auf sich selbst, nur weil wir es zum Speichern seines eigenen Speicherplatzes verwendet haben.

  • Ich verstehe nicht, warum im ersten Beispiel a zeigt nicht auf sich selbst, da sein Inhalt eine Speicheradresse ist (Definition eines Zeigers, nicht wahr?) – in diesem Fall seine eigene Adresse – und keine ganze Zahl (er wurde in a gecastet). int*). Also, offensichtlich, &a und a produzieren das gleiche Ergebnis, wenn sie gedruckt werden, sagen wir 0xABCD. Aber jetzt kann ich legal schreiben *a = 0x1234und cout << a zeigt, dass die dereferenzierter Zeiger, a wurde verändert : &a = 0xABCD aber a = 0x1234. Liege ich irgendwo falsch?

    – Greg82

    29. August 2014 um 12:08 Uhr


  • @ Greg82 Weil per Definition von int *a;, a muss auf ein zeigen int aber danach a=(int*)&a; Die Variable a würde auf ein hinweisen int * was es nicht tun sollte. (Fürs Protokoll, die Art von &a ist int **) Da Zeiger als ganze Zahlen behandelt werden (zumindest normalerweise und vielleicht so, wie es die C-Standards vorschreiben, ich weiß nicht), funktionieren die Dinge, aber es muss nicht der Fall sein in einer Sprache oder Architektur, die Zeiger anders als ganze Zahlen behandelt.

    – SO stinkt

    7. März 2015 um 21:49 Uhr


Nun, zuerst würde ich den Code ändern:

int **a;
a = (int **)&a;  // otherwise you get a warning, since &a is int ***

Ich bin mir nicht sicher, warum Sie das tun würden, aber es ist erlaubt.

printf("The address of a is %p\n", &a);
printf("a holds the address %p\n", a);
printf("The value at %p is %p\n", a, *a); // the *a is why we made a an int **

Sie sollten dasselbe ausdrucken.

The address of a is 0x7fffe211d078
a holds the address 0x7fffe211d078
The value at 0x7fffe211d078 is 0x7fffe211d078

Beachten Sie, dass dies keine gute Idee ist, da die allererste Besetzung a = (int **)&a ist ein Hack zum Erzwingen a einen Wert zu halten, den es nicht halten sollte. Sie erklären es an int ** aber versuchen, ein zu erzwingen int *** hinein. Technisch gesehen sind die Größen gleich, aber im Allgemeinen tun Sie das nicht, weil die Leute das erwarten int * enthält die Adresse von etwas, das als verwendet werden kann intund so weiter.

Ja und nein, denn der Typ des Zeigers ist fast so wichtig wie der Wert des Zeigers.

Ja, ein Zeiger kann die Position eines Zeigers auf sich selbst enthalten; sogar ein long kann die Position eines Zeigers auf sich selbst enthalten. (Ints können das normalerweise, aber ich weiß nicht, ob das überall garantiert ist.)

Es gibt jedoch keinen Typ, der diese Beziehung darstellt. Wenn Sie einen Zeiger haben, der auf sich selbst zeigt, haben Sie tatsächlich einen anderen Typ, wenn Sie ihn dereferenzieren. So:

void *p = &p;
// *p is illegal, even though you probably wanted it to equal 'p'
if( *p != p ) {
    printf("Something's wrong");
}

int *i = (int*)&i;
// The following statement is still illegal
if( *i == i ) {
    printf("The universe works!");
}

Ich würde sagen, die Antwort ist “nein”, weil es nicht funktionieren wird, wenn Sie das Typsystem nicht missbrauchen. Ich denke, es ist ein Hinweis darauf, dass Sie etwas falsch machen (obwohl es manchmal sicherlich notwendig ist).

Das Dereferenzieren eines Zeigers führt zu einem Wert von ihm Werttyp (z. B. dereferenzieren an int* gibt dir ein intein int*s-Werttyp). Damit eine Variable auf einen Zeiger zeigt, müsste ihr Werttyp sein int*was bei einem nicht der Fall ist int* wie kürzlich bekannt gegeben. Damit ein Zeiger auf sich selbst zeigt, müsste man also eine Art Umwandlung durchführen, um ihn vom Compiler zu bekommen:

int* a;
a = reinterpret_cast<int*>(&a);

Zum Dereferenzieren adann hätten Sie eine int dessen Wert zufällig die Adresse ist, an der a liegt (Mod-Abschneiden der Adresse, um den Typ anzupassen), aber es ist immer noch eine int und nicht ein int*was eine weitere Besetzung erfordern würde.

Ein Zeiger auf einen Zeiger wird oft als a bezeichnet handhabendas ist ein anderer Typ (int**) als ein Zeiger (int*). (Beachten Sie, dass ein int** Handle hat den Werttyp int*.)

  • Dies ist eine C++-Antwort auf eine C-Frage. Ansonsten interessante Antwort.

    – Jared Updike

    14. Februar 2012 um 22:25 Uhr

Ja, ein Zeiger kann auf sich selbst zeigen, wie in den Antworten erwähnt.

Ein möglicher Anwendungsfall ist, dass wir diesen Trick anstelle von NULL-Zeigern verwenden können. Sie können int * p = (int *)&p initialisieren und dies später überprüfen, um zu sehen, ob der Zeiger gültig ist oder nicht. Dies hätte beispielsweise in einem System verwendet werden können, in dem wir wollten, dass 0x0 und der gesamte Adressbereich gültige Adressen sind.

Sie können diesen Trick auch in speziellen C-Programmen verwenden, die bei der Verwendung von NULL-Zeigern nicht abstürzen würden, da Sie sie vollständig vermeiden würden und das System bei der Dereferenzierung nicht abstürzen würde. Dies führt zu fehlerhaftem Verhalten, kann aber in bestimmten Situationen beim Debuggen hilfreich sein.

  • Dies ist eine C++-Antwort auf eine C-Frage. Ansonsten interessante Antwort.

    – Jared Updike

    14. Februar 2012 um 22:25 Uhr

Benutzeravatar von zaharpopov
Zaharpopov

Ja, es ist möglich, auf sich selbst zu zeigen.

int* a;
a = &a;

Aber keinen Nutzen haben, zumindest explizit so.

  • Was Typen hervorbringt. &a hat den Typ int** und weist diesen zu a was ein int* ist, ist ein undefiniertes Verhalten (zumindest wenn Sie versuchen, den Zeiger zu verwenden.

    – Nr

    28. März 2010 um 18:42 Uhr

  • Fehler: ‘int**’ kann bei der Initialisierung nicht in ‘int*’ konvertiert werden

    – Swapnil

    27. November 2018 um 3:45 Uhr

1407270cookie-checkKann ein Zeiger jemals auf sich selbst zeigen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy