2016-05-26 22 views
1

Ich weiß, Zeiger eines Typs kann auf Zeiger eines anderen Typs gegossen werden, zum Beispiel bei der Verwendung von malloc der void-Zeiger kann auf einen anderen Typ gegossen werden. Aber ich habe diesen Teil des Codes gesehen, der einen Wert direkt in einen Zeigertyp umwandelt. Kannst du mir helfen zu verstehen, was vor sich geht?Zeiger Typ Casting

#include <stdio.h> 
#include <stdlib.h> 

enum otype {INT, SYM, CONS}; 
typedef struct obj { 
    enum otype type; 
    struct obj *p[1]; 
} obj; 

int 
main(void) 
{ 

    struct obj *o1 = (obj *) 10; 
    printf("%d\n", (int) o1); 

    struct obj *o2 = (obj *) "abc"; 
    printf("%s\n", (char *) o2); 

    return 0; 
} 
+1

Nein, Sie werfen keinen 'void *' Zeiger auf einen anderen Typ. Das ist der Punkt, warum 'malloc' ein' void * 'zurückgibt, so dass es direkt dem gewünschten Zeigertyp zugewiesen werden kann. Auch warum "memcmp" 'void *' Argumente nimmt, so dass Sie jeden Typ übergeben können. –

+0

Was Sie mit Ihren Umwandlungen tun, ist eine schlechte Verwendung von Zeigern aus dem Compiler zu verstecken. Und was ist der Zweck des Ein-Element-Arrays? Struct obj * p [1]; '? –

+0

Wieder der Kommentar unten. \t Ich denke, der Punkt des obigen Codes ist, dass der Zeiger nicht dereferenziert wird; es wird vielmehr sein, dass obj den Enum-Typ INT, SYM usw. enthalten kann und das Array darin auf (obj *) 10 oder (obj *) "abc" zeigt; Später können diese Werte dann durch erneutes Konvertieren mit (int) oder (char *) wieder abgerufen werden. So verstehe ich es. Aber ich habe diese Art der Verwendung von Pointer noch nicht gesehen, also frage ich nach dem, was vor sich geht und ob ich falsch liege oder etwas vermisse – james0011

Antwort

0

Sie können jeden beliebigen Zeigertyp sowie einige Nicht-Zeigertypen beliebig in einen anderen Zeiger einbetten. Dies bedeutet nicht, dass das Ergebnis eine nützliche Bedeutung hat.

Ein Zeiger ist nur eine ganze Zahl, die die Speicheradresse einiger Daten enthält. Wenn Sie es von einem Typ auf einen anderen umwandeln, teilen Sie dem Compiler mit, dass die gleiche Zahl (Speicheradresse) sich auf einen anderen Typ bezieht. Abhängig von den Quell- und Zieltypen kann das Ergebnis von nützlich bis völlig bedeutungslos reichen.

Taking Ihr Beispiel:

struct obj *o1 = (obj *) 10; 

Diese den Compiler Speicheradresse zu behandeln sagt 10 (0xa), als ob es eine Struktur des Typs obj enthält. Da die Speicheradresse 10 dies höchstwahrscheinlich nicht enthält, führt der Versuch, diesen Zeiger tatsächlich zu dereferenzieren, zu undefiniertem Verhalten.

struct obj *o2 = (obj *) "abc"; 

Hier sind wir auf etwas festeren Böden (nicht viel). Das liegt daran, dass wir, obwohl wir nicht wissen, welche Adresse o2 hat, wissen, was in diesem Speicher ist. Dieser Speicher enthält die Sequenz 0x61 0x62 0x63 0x00. Nehmen wir einen kleinen Endian-Rechner an (was die meisten heutzutage sind), bedeutet dies, dass Ihr Enum den (ungültigen) Wert 6513249 enthält und Ihr Zeiger so undefiniert ist wie im ersten Fall.

+0

Hallo, ich denke, der Punkt des obigen Codes ist, dass der Zeiger nicht dereferenziert wird; Vielmehr wird obj den Enum-Typ INT, SYM usw. enthalten können.und das Array darin zeigt auf (obj *) 10 oder (obj *) "abc"; Später können diese Werte dann durch erneutes Konvertieren mit (int) oder (char *) wieder abgerufen werden. So verstehe ich es. Aber ich habe diese Art von Zeiger noch nicht gesehen, also frage ich nach dem, was vor sich geht und ob ich falsch liege oder etwas verpasse. – james0011