2017-12-30 79 views
-1

Ich bin schwer zu verstehen, wie Zeiger funktionieren. Die Art, wie ich es bekam, ist, dass, wenn ich einen Zeiger auf, sagen wir, Int, deklariere ich sowohl eine Variable, die eine Adresse enthält (die initialisiert werden muss, um sogar auf dem Int zu operieren) und eine int-Variable. Visuell würde ich dies so darstellen (Adresse; Int). Wenn ich zum BeispielPointer von Zeiger und Pass durch Referenz

int* number; 

deklariert hätte, hätte ich "number" als Adressvariable und "* number" als int-Variable.

Ebenso sollte das Deklarieren von etwas wie int ** d bedeuten, einen Zeiger auf (Adresse; int) zu erzeugen. Das wäre [Adresse; (Adresse; Int)].

In diesem Sinne habe ich versucht, den Int-Wert von ** d zu ändern, indem Sie eine externe Funktion, incrementer_3, und diese so genannte Pass by Referenz, aber ich bekomme einen Fehler bei der Laufzeit. Also habe ich mich gefragt, was ich vermisse.

#include <stdio.h> 

void incrementer(int* a) { 
    (*a)++; 
} 

void incrementer_2(int** a) { 
    (**a)++; 
} 

void incrementer_3(int*** a) { 
    (***a)++; 
} 

int main() { 
    int b = 7; 
    incrementer(&b); 
    printf("%d\n", b); 

    int* c = (int*)malloc(sizeof(int)); 
    *c = 4; 
    incrementer_2(&c); 
    printf("%d\n", *c); 

    int** d = (int**)malloc(sizeof(int*)); 
    **d = 6; 
    incrementer_3(&d); 
    printf("%d\n", **d); 

    system("pause"); 
} 

FYI der Teil, wenn ich b und c arbeite, funktioniert gut. Nebenbei habe ich mich gefragt, ob es möglich ist, den Wert von * c zu ändern, indem Sie die Funktion "incrementer" und nicht "incrementer_2" verwenden. In der Tat dachte ich nur, dass ich einfach aus dem Haupt

geschrieben haben könnte
incrementer(&(*c)); 

oder in einer einfacheren Art und Weise

incrementer(c); 

aber keiner von ihnen zur Laufzeit arbeiten.

+0

'** d = 6;' - dies ruft undefiniertes Verhalten auf. Sie haben '* d' nicht initialisiert. –

+0

Warum nicht einfach 'int * c = & b;' und 'int ** d = & c;'? –

+0

Beachten Sie auch, dass C nicht "durch Verweis übergeben" hat, es kann nur * durch die Verwendung von Zeigern und der Adresse-of-Operator * emuliert werden. –

Antwort

0

Sie müssen daran denken, dass ein Zeiger nicht wirklich auf etwas verweisen muss, und selbst wenn es sich auf etwas bezieht, dass etwas nicht gültig sein muss. Den Überblick über diese Dinge zu behalten, ist Ihre Aufgabe als Programmierer.

Per Konvention erhält ein ungültiger Zeiger den Wert 0 (was schließlich zu NULL kommt), aber das ist nur Konvention, andere Werte können unter Umständen verwendet werden.

Also, mit "int * Nummer;" Sie haben einen Zeiger auf int deklariert, aber weil er nicht initialisiert ist, haben Sie absolut keine Ahnung, welchen Wert er enthält. Das Dereferenzieren an diesem Punkt ist ein undefiniertes Verhalten - was bedeutet, dass die meisten passieren können, wenn Sie es versucht haben Realität wird es wahrscheinlich Ihr Programm einfach zum Absturz bringen.

Das Problem:

int** d = (int**)malloc(sizeof(int*)); 
    **d = 6; 

ist, dass während d initialisiert * d nicht. Sie tun können:

*d = malloc(sizeof(int)); 

oder

*d = c; 

aber * d muss auf etwas zu spitz, bevor Sie ** d verwenden können.

+0

Vielen Dank, die Idee ist klar und das Programm funktioniert jetzt. – thegreatestdoge

0

Das Problem ist, dass Sie Speicher für die int* reservieren, aber Sie keine Speicher für die int zuweisen oder den Zeiger der int setzen. Sollte sein:

int** d = (int**)malloc(sizeof(int*)); *d = (int*)malloc(sizeof(int)); **d=6;

Die Art und Weise habe ich es, dass, wenn ich einen Zeiger auf, sagen wir erklären, int, Ich schaffe sowohl eine Variable, die eine Adresse enthalten werden (das initialisiert werden muss sogar auf der int) und eine int-Variable zu operieren.

Nein, wenn Sie einen Zeiger deklarieren, erstellen Sie eine Variable, die weiß, wie eine Adresse enthalten ist. Wenn Sie malloc() verwenden, reservieren Sie Speicher. malloc() gibt eine Adresse zurück, die Sie Ihrem Zeiger zuweisen können.

P.S. - incrementer(c) sollte gut funktionieren

+0

Danke, es funktioniert jetzt. Über den letzten Punkt habe ich falsch gemeint, dass ich angenommen habe, dass das Deklarieren eines Zeigers auf int bedeutet, eine Variable zu erstellen, die zwei Felder enthält, eines zum Enthalten einer Adresse, das andere zum Enthalten eines int-Wertes. Ist diese Vermutung sogar wahr? – thegreatestdoge

+0

Gern geschehen. Nein, ein Zeiger enthält nur einen Wert - eine Adresse. Sie können Operatoren wie '* verwenden. -> 'um den Wert in der Speicheradresse zu behandeln, auf die der Zeiger zeigt. –

0
int b 

b ist ein int. Wir können uns darauf beziehen, indem wir b schreiben.

b = 7; 

Hier vergeben wir eine Nummer an b.

int* c 

c ist ein Zeiger, der auf eine int anweisen. Wir können darauf Bezug nehmen int durch Schreiben *c.

c = (int*)malloc(sizeof(int)); 

Wir haben ein Stück Speicher gefunden, dass ein int, und einen Zeiger halten kann, die auf dem Stück weist, und an c zugeordnet. Alles ist gut.

*c = 4; 

Hier vergeben wir eine Nummer zu *c. Sehen? *c verhält sich genau wie b. Aber das liegt nur daran, dass wir es mit einem gültigen Zeiger initialisiert haben! Ohne diese wäre *c = 4; ungültig.

int** d 

d ist ein Zeiger, int* auf eine Sache des Typs zeigen sollte, die wir mit dem Schreiben *d verweisen. Diese int* Sache wiederum sollte auf eine int hinweisen, auf die wir uns beziehen können, indem wir **d schreiben.

d = (int**)malloc(sizeof(int*)); 

Wir haben ein Stück Speicher gefunden, dass ein int* und einen Zeiger halten kann, die auf dem Stück weist, und an d zugeordnet. Alles ist gut. Jetzt, dass int* rufen wir *d, was zeigt es?

Nichts. Um es auf etwas zu verweisen, hätten wir ein Stück Speicher finden können, das eine int enthält, und einen Zeiger gemacht, der auf dieses Stück zeigt, und es unserem *d zugewiesen, genauso wie wir es früher mit c gemacht haben. Sehen? *d verhält sich genau wie c. Um *c zu verwenden, mussten wir zuerst c mit einem gültigen Zeiger initialisieren. Um **d zu verwenden, müssen wir zuerst *d mit einem gültigen Zeiger initialisieren.

*d = (int*)malloc(sizeof(int));