2017-04-30 6 views
0

Ich möchte auf den Wert mit p-Zeiger zugreifen können. Aber wenn ich den Zeiger p verwende, bekomme ich immer die Variable b gleich null. Bitte beachten Sie das Code-Snippet unten.Warum kann ich in C++ nicht mit einem anderen Zeiger auf int zugreifen?

basepointer = malloc(512);  
*((int*)basepointer+32) = 455; // putting int value in memory 
void *p = basepointer + 32;  // creating other pointer 
int a,b; 
a = *((int*)basepointer+32); // 455, retrieving value using basepointer 
b = *((int*)p);     // 0, retrieving value using p 

Warum passiert es so? Wie kann ich mit meinem p-Zeiger auf den Wert zugreifen?

+1

Versuchen Sie '* (int *) (Basiszeiger + 32) = 455;' in Ihrer zweiten Zeile stattdessen. Dann gehen Sie und lesen Sie über Zeigerarithmetik. – aragaer

+1

@aragaer Keine gute Idee, wenn 'basepointer' den Typ' void * 'hat. – aschepler

+0

Was ist die Art von Basispointer? – Bathsheba

Antwort

3

Ich kann nicht eine gute doppelte Antwort finden, also hier ist was los:

Pointer-Arithmetik geschieht immer in Einheiten der Basistyp des Zeigers. Das heißt, wenn Sie T *ptr (ein Zeiger auf einen Typ T) haben, dann ist ptr + 1 nicht das nächste Byte im Speicher, sondern das nächste T.

Mit anderen Worten: Sie einen Zeiger wie eine Kombination aus einem Array vorstellen können und ein Index:

T *ptr; 
T array[/*some size*/]; 
ptr = &array[n]; 

Wenn ptr ist ein Zeiger auf array[n] (das n-te Element), dann ist ptr + i ein Zeiger auf array[n + i] (das (n + i) -te Element).

Lassen Sie uns einen Blick auf den Code nehmen:

*((int*)basepointer+32) = 455; 

Hier sind Sie basepointer zu (int*) Gießen, dann 32 ihm hinzufügen. Dies gibt Ihnen die Adresse des 32. int nach basepointer. Wenn Ihre Plattform 4-Byte-Ints verwendet, ist der tatsächliche Offset 32 * 4 = 128 Bytes. Hier speichern wir 455.

Dann tun Sie

void *p = basepointer + 32; 

Dies ist technisch ungültigen Code, weil basepointer ein void * ist, und Sie können Arithmetik in Bezug auf void nicht tun, weil void keine Größe hat. Als Erweiterung unterstützt gcc dies und gibt vor, void hat die Größe 1. (Aber Sie sollten wirklich nicht verlassen: cast unsigned char * wenn Sie wollen byteweise Adressierung.)

Jetzt p ist bei Offset 32 nach basepointer.

a = *((int*)basepointer+32); 

Wiederholt die Zeigerarithmetik von oben und ruft den Wert aus int 32 versetzt (d.h. Byte 128 Offset), die 455 noch ist.

b = *((int*)p); 

Dies ruft der int Wert bei Offset-Byte gespeichert 32 (die int Offset 8 in diesem Beispiel entsprechen würde). Wir haben nie etwas hier gespeichert, so b ist im Wesentlichen Müll (es ist zufällig 0 auf Ihrer Plattform).


Die kleinste Änderung dieses Code zu machen, wie wahrscheinlich zu erwarten ist

void *p = (int *)basepointer + 32; // use int-wise arithmetic to compute p 
0

void-Zeiger-Arithmetik in C/C++ illegal ist, ermöglicht GCC es als Erweiterung.

müssen Sie diese Zeile ändern:

void *p = basepointer + 32; 

zu

void *p = basepointer + 32 * sizeof(int); 

weil Zeigerarithmetik relativ zu dem Typ Größe berechnet wird.

zum Beispiel:

wenn sizeof (int) = 4 und sizeof(short) = 2

und int *p hat Adresse 3000
und short *sp hat Adresse 4000

dann p + 3 = p + 3 * sizeof(int) = 3012
und sp + 3 = sp + 3 *sizeof(short) = 4006

für void ist es 1 wenn der Compiler es erlaubt.

Verwandte Themen