2017-03-16 4 views
2
#include <stdio.h> 
typedef struct { 
    int data; 
    char * string; 
}Node; 

Node * init(){ 
    Node node; 
    node.data = 5; 
    node.string = "hello"; 
    Node * point = &node; 
    return point; 
} 
int main() { 
    Node * test = init(); 
    printf("%d\n", test->data); 
    printf("%d", test->data); 
} 

Warum bewirken die letzten beiden printf-Anweisungen unterschiedliche Ergebnisse? Ich vermute, dass etwas damit zu tun hat, wie ich meinen Testzeiger zugewiesen habe, aber ich weiß nicht, wie ich es beheben soll.C-Sprache: Warum drucken diese beiden printf-Anweisungen verschiedene Dinge?

Antwort

3

In Ihrem Fall ist node eine Variable lokal für die Funktion init() und doch geben Sie die Adresse von diesem zurück. Sobald die Funktion zurückgegeben wird, gibt es keine node mehr.

Nach dem Zurückkehren der Funktion auf den Rückgabewert wird auf ungültigen Speicher zugegriffen, der undefined behavior verursacht.

Sie können jedoch die Strukturvariable selbst, nicht einen Zeiger darauf zurückgeben und den Rückgabewert im Aufrufer in einer anderen Variable sammeln, es wird funktionieren.

+0

Welche Änderungen an dem Code müsste ich beheben? – Madnobleman

+0

@weijazhou Bitte lesen Sie den letzten Absatz in der Antwort, nur aktualisiert es. :) –

0

Knoten wird als lokale Variable in der Funktion init() definiert, so dass der Speicher freigegeben wird, nachdem die Funktion zurückgegeben wurde.

Sie sollten entweder Knoten als globale Variable definieren (ich mag keine Globals :-)) oder Speicher durch Aufruf von malloc reservieren.

node = malloc(sizeof(Node)); 

Vergessen Sie nicht, den Speicher freizugeben, wenn Sie keinen Knoten mehr benötigen.

0

aktualisieren init() zurückzukehren struct:

Node init(){ 
    Node node; 
    node.data = 5; 
    node.string = "hello"; 
    return node; 
} 

es dann zugreifen wie folgt aus:

Node testNode = init(); 
printf("%d\n", testNode.data); 
printf("%d", testNode.data); 

Oder wenn Sie möchten, wie dieser Zeiger verwenden:

Node testNode = init(); 
Node* pointerToNode = &testNode; 
printf("%d\n", pointerToNode->data); 
printf("%d", pointerToNode->data); 

Und der Grund dafür ist, wie @Sourav antwortete, dass die Daten nicht mehr gültig sind.

Ich hoffe, das ist nützlich.

1

Ja, Ihr Code weist ein undefiniertes Verhalten auf, weil er einen Zeiger auf ein lokales Objekt der Funktion zurückgibt. Aber es scheint so, als wäre Ihr Ansatz fehlgeleitet. Ihre init-Funktion soll eine Struktur mit einem richtigen Anfangswert initialisieren, es ist nicht nötig, dafür einen Zeiger zurückzugeben. Sie haben drei Optionen:

  1. Rückgabewert, wie eine andere Antwort vorgeschlagen.

  2. Übergeben Sie die Adresse einer Struktur für die zu initialisierende Funktion. Dies befreit den Rückgabewert, so dass Sie können Erfolg oder Misserfolg signalisieren:

    bool init(Node *node) { // must include stdbool.h 
        if(!node) 
         return false; 
    
        node->data = 5; 
        node->string = "hello"; 
        return true; 
    } 
    
    //... 
    
    Node test; 
    if(!init(&test)) { 
        //failed to initialize, handle the error 
    } 
    
  3. die Funktion vollständig verzichten und einen Makro liefern, die für den Knoten Anfangswert steht:

    #define NODE_INIT_VAL { \ 
        .data = 5, .string = "hello", \ 
    } 
    

    Dies ermöglicht es Ihnen, Schreiben Sie einfach Node test = NODE_INIT_VAL;. Sie möchten auch alle Objekte mit statischer Speicherdauer initialisieren.

Verwandte Themen