2017-06-19 1 views
0

Meine Frage ist in Bezug auf diese beiden Fälle:C - Rückgabe eines lokalen Zeiger vs lokale Variable

#include <stdio.h> 
int *foo1(); 
int *foo2(); 

int main() 
{ 
    printf("so it's %d\n",*foo1()); 
    printf("so it's %d\n",*foo2()); 
} 

int *foo1() 
{ 
    int i1 = 5; 
    return &i1; 
} 

int *foo2() 
{ 
    int i2 = 5; 
    int *p = NULL; 
    p = &i2; 
    return p; 
} 

case1: Wenn sein der Fall mit foo1(), so erhalten wir einen Fehler, da wir zurückkehren wollen eine Kopie der Adresse Hauptdaten, die es wurde gelöscht

case2 (wenn wir foo1() Funktion verlassen): Aber in foo2(), es nicht gibt einen Fehler obwohl wir eine Kopie zurückkehren zu ein Zeiger der lokalen Variablen, dessen Daten gelöscht werden d nachdem wir die Funktion foo2() verlassen haben, warum ist das so?

TL; DR: Warum foo2() gibt keinen Fehler, aber foo1() tut?

TIA.

+0

C oder C++? Auch, g ++, [gibt eine Warnung für beide] (http://coliru.stacked-crooked.com/a/5ee45849a93cd26d) – NathanOliver

+0

Ich glaube, es hat etwas damit zu tun, dass * foo1 * einen rvalue während * foo2 zurückgibt * gibt einen Lvalue zurück, der eine gültige Rückgabe ist, obwohl die Zeigeradresse selbst ungültig ist. – abe

+0

Warum das doppelte Tag? – StoryTeller

Antwort

8

Das Verhalten beider Funktionen foo1 und foo2 sind undefined, in C und C++.

Sie dürfen nicht dereference ein Zeiger, der auf eine Variable mit automatischer Speicherdauer verweist, die nicht mehr im Bereich ist.

Morgen, foo2() kann Ihnen auch einen Fehler geben. Oder der Compiler könnte Ihre Katze essen.

+0

Nützliche Antwort - Ich überprüfe meinen Code immer dreifach, um sicherzustellen, dass meine Katze nicht vom Compiler gegessen wird. – Peri461

+0

tue ich auch; Ich habe meine Katzen aus dem Studium entfernt. – Bathsheba

+0

Wir sollten auf jeden Fall Codiermethoden vermeiden wollen, die Compiler dazu bringen, Katzen zu essen! : O –

1

In beiden Fällen rufen Sie undefined behavior auf, indem Sie einen Zeiger auf eine lokale Variable zurückgeben und diesen dereferenzieren.

Das Aufrufen von undefiniertem Verhalten bedeutet nicht, dass Sie immer abstürzen. Es bedeutet, dass das Verhalten des Programms nicht definiert ist. Es könnte abstürzen, es könnte seltsame Ergebnisse ausgeben, oder es könnte richtig funktionieren. Wie Sie gesehen haben, manifestiert sich dieses Verhalten auf zwei Arten in Ihrem Programm.

Eine scheinbar nicht zusammenhängende Änderung, z. B. das Hinzufügen einer nicht verwendeten lokalen Variablen oder eines printf zum Debuggen, kann die Art und Weise ändern, in der sich undefiniertes Verhalten manifestiert.

1

Beide sind undefiniertes Verhalten, Sie können sich nicht darauf verlassen, dass der Compiler Warnungen für undefiniertes Verhalten gibt.

Sie machen im Wesentlichen dasselbe in beiden Funktionen und in der Tat können beide dazu führen, dass derselbe Assemblercode erzeugt wird.

1

Das Verhalten von case1 und case2 sind nicht definiert, Sie können Zeiger auf lokale Variable nicht zurückgeben