2014-10-05 25 views
5

Betrachten Sie den folgenden Code ein:Müssen wir eine Struktur malloc?

struct Node { 
    void* data; 
    int ref; 
    struct Node* next; 
}; 
typedef struct Node* NodePtr; 

ich gefunden habe, dass ich segfaults bin immer wenn ich versuche, mit NodePtr den Feldern nichts zu tun. Z.B .:

NodePtr node; 
node->ref = 1; 

So zugewiesen ich etwas Platz für die NodePtr, und jetzt scheint es zu funktionieren. Warum ist das? Meine Vermutung ist, dass, da Knoten nur ein Zeiger ist, er keinen Speicher für seine Felder hat. So

Ich versuchte, die NodePtr zu initialisieren:

NodePtr node = { 
    node->data = 0; 
    node->next = NULL; 
    node->ref = 0; 
}; 

Und na ja, ich habe diesen Fehler:

error: expected â}â before â;â token 

Dies läuft darauf hinaus, vier Fragen nach unten:

  1. Wenn meine Vermutung ist falsch, warum funktioniert es nicht, wenn ich malloc() nicht verwende?
  2. Warum funktioniert meine Initialisierung nicht?
  3. Würde die Initialisierung einer Struktur Speicher auf dem Stack anbieten und mein Problem lösen?
  4. Wenn nicht, habe ich eine Alternative zum Speicher für jede Struktur zuweisen, die ich verwende?
+0

Sie brauchen nicht 'malloc'. Zum Beispiel: struct Node n = {NULL, 42, NULL}; Sie haben nur Syntaxfehler überall. – juanchopanza

+2

Sie müssen keinen Speicher zuweisen, wenn Sie ein Objekt ohne Zeiger erstellen. – Ares

+1

Ihre 'NodePtr'-Initialisierung ist nicht einmal die richtige C-Syntax, dies kann nicht der Code sein, den Sie ausprobiert haben. –

Antwort

17

A struct automatisch zugeordnet werden kann, aber Sie werden einen Zeiger auf struct mit denen Speicherplatz für das Ziel nicht reservieren struct. Das ist der Grund, warum du segfault bekommst.

Der Grund Ihrer Initialisierung falsch ist, ist, dass Sie structMitglieder initialisiert wird, nicht die struct selbst. Auch das machst du falsch.

Es gibt 2 Möglichkeiten zur Initialisierung eines struct:

  1. Mit Stapel reserviert struct:

    struct example { 
        int foo; 
    }; 
    int main() { 
        struct example e; 
        e.foo=1; 
    } 
    
  2. Haufen Verwendung zugewiesen struct mit Hilfe von malloc():

    struct example { 
        int foo; 
    }; 
    int main() { 
        struct example *e=malloc(sizeof(struct example)); 
        e->foo=1; 
    } 
    

Bitte beachten Sie, dass, wenn Sie Wert auf ein Mitglied einer struct von seinem Zeiger zuweisen (Heap zugewiesen struct) Sie ‚->‘ zu verwenden, haben aber für die normale Struktur (der Stapel zugewiesen eins) Sie ‚.‘ verwenden .

1

Ihre Annahme ist richtig: Ein Zeiger hat keinen Speicher für das Objekt, auf das er selbst zeigen soll, Sie müssen ihn selbst zuweisen.

Jedenfalls, wie Juanchopanza bemerkt: Sie brauchen keinen Zeiger und eine Speicherzuweisung, wenn Sie mit einem lokalen Objekt zu tun haben.

Beide Techniken folgen:

typedef struct Node { 
    void* data; 
    int ref; 
    struct Node* next; 
} Node; 
typedef struct Node* NodePtr; 

int main() { 

     NodePtr node = (NodePtr)malloc(sizeof(Node)); 
     node->data = 0; 
     node->next = 0; 
     node->ref = 42; 
     printf("%d", node->ref); 

     Node obj = {0,42,0}; // this is not on the heap 
     printf("%d", obj.ref); 

Die anderen Schreibweisen Sie versucht haben, sind nicht richtig. Nicht einmal ein Teil der Sprache.

2

Ein Zeiger ist keine Struktur. Es ist eine Zahl, die C mitteilt, wo sich die Struktur im Speicher befindet. Jede Variable mit dem Typ NodePtr ist im Wesentlichen eine Zahl.

Wie macht es also Sinn, eine Variable vom Typ NodePtr auf eine Struktur zu setzen? Eine Struktur ist keine Zahl!

Wenn Sie es mit NodePtr node deklarieren, kann es auf einen nicht definierten Wert wie 0 gesetzt werden. Sie können nicht auf diesen Speicher zugreifen, was zu einem segfault führt. Stattdessen suchen Sie nach Speicher, der mit malloc() verwendet werden soll, und stellen Sie den Variablenpunkt dort ein, wo seine Felder verwendet werden können.


zu potrzebie Kommentar zu antworten, so scheint es, mit Streichern zu arbeiten, aber das ist wirklich nur syntaktischer Zucker:

#include <stdio.h> 

int main() { 
    char *a = "Does this make sense?"; 
    printf("%d\n", a); // %u is the correct one, but this is for illustrational purposes 

    return 0; 
} 


> test.exe 
4214884 
+0

Es sollte sinnvoll sein, Sie können es mit Strings tun. – potrzebie

+0

@potrzebie 'char * x =" ... "'? Das ist syntaktischer Zucker, es ist immer noch eine Nummer und die Zeichenfolge wird woanders gespeichert. War das der Grund für die Ablehnung (wenn du es warst)? – itdoesntwork

Verwandte Themen