2016-11-02 6 views
0

Das Snippet übergibt den Wert id an eine Routine, die eine allgemeine void * Struktur annimmt. Ich bin verwirrt, warum es funktioniert: Warum können Sie die long zu void* werfen und es mit einer long zurückwerfen.Wert durch Zeiger auf void übergeben

Insbesondere dachte ich, wenn Sie mit Zeiger übergeben möchten, dann sollten Sie die Adresse der Variablen wie &id an die test() Funktion übergeben.

#include <stdio.h> 

void test(void * id) { 
    long myid; 
    myid = (long) id; 
    printf("my id is %ld\n", myid); 
} 

int main() { 
    long id = 5; 
    test((void *)id); 
} 

Antwort

4

Es funktioniert, weil (die auf dem System!) Der void* Zeiger selbst enthält genügend Bits alle Bits eines long Wert zu halten. Dies ist nicht tragbar.

Sie haben recht, dass Sie normalerweise long* zu void* und zurück werfen würden. Das ist tragbar.

1

Es funktioniert, weil Zeiger nur Zahlen sind.

Ihre Testfunktion "denkt", dass sie einen Zeiger auf Speicherplatz 5 erhalten hat, und Sie können diese Adresse natürlich ausdrucken. Sie könnten diesem Ort nichts zuweisen, daher würde * myid = 42 einen Segmentierungsfehler verursachen. Das Übergeben einer Zahl an einen Zeiger ist syntaktisch korrekt, sodass Ihr Compiler nicht stöhnt, aber keinen Sinn ergibt. Führen Sie diesen Code aus und sehen Sie, wie ein Zeiger aussieht, wenn er gedruckt wird (ignorieren Sie die Warnung Ihres Compilers).

#include <stdio.h> 

void test(void *id, long *foo) { 
    long myid; 
    myid = (long) id; 
    printf("my id is %ld, %ld\n", myid, foo); 
} 

int main() { 
    long id = 5; 
    long foo; 
    foo = 42; 
    test((void *)id, &foo); 
} 
+0

Das ist nicht die richtige Art, den Wert von 'foo' zu drucken. Benutze 'printf ("% p ", (void *) foo);/* besser */'oder' printf ("% ld", (lang) foo);/* schlechter */' – user694733

+0

Zeiger sind nicht" nur Zahlen ". In der Regel sind 8086 "far" -Zeiger zwei Zahlen. (Segment/Offset) – MSalters

1

Ich bin verwirrt, warum es funktioniert: Warum können Sie die lange werfen * ungültig zu erklären und es wieder mit einem langen gegossen.

long id = 5; 
test((void *)id); 

Dies ist tatsächlich gültig. Sie wollen im Wesentlichen einen void Zeiger auf die Funktion test übergeben, der Zeiger enthält die Adresse 5.

In void test(void * id), werfen Sie diesen Zeiger zurück auf long, die auch gültig ist.

Beachten Sie in Ihrem Code, dass Sie niemals den Zeiger ablehnen, damit die Dinge funktionieren. Wenn Sie den Zeiger id in test dereferenzieren, würde das normalerweise wegen eines schlechten Speicherzugriffs zu einem Segmentfehler führen.