Nicht initialisiertes Variablenverhalten in C++

Lesezeit: 5 Minuten

Benutzer-Avatar
omidh

Ich habe mich selbst überprüft, ich habe ein Programm wie dieses geschrieben

int main() {
 int i;
 cout << i;
 return 0;
}

Ich habe das Programm ein paar Mal ausgeführt und das Ergebnis war die ganze Zeit gleich Null. Ich habe es in C versucht und das Ergebnis war das gleiche.

Aber mein Lehrbuch sagt

Wenn Sie eine Variable, die in einer Funktion definiert ist, nicht initialisieren, bleibt der Variablenwert undefiniert. Das bedeutet, dass das Element den Wert annimmt, der sich zuvor an dieser Stelle im Speicher befand.

Wie ist das möglich, wenn das Programm einer Variablen immer einen freien Speicherplatz zuweist? Wie könnte es etwas anderes als Null sein (ich gehe davon aus, dass der Standardwert für freien Speicher Null ist)?

  • Es ist ein undefiniertes Verhalten in C++ und C. Sie sagten aber C im Titel cout stammt aus C++.

    – Shafik Yaghmour

    11. Mai 2015 um 16:03 Uhr


  • Und weil es undefiniert ist, “darf” (aber nicht muss) der Compiler das Programm so generieren, dass 0 zugewiesen wird, bevor Sie es verwenden.

    – Abweichler

    11. Mai 2015 um 16:06 Uhr


  • Welches Lehrbuch ist das?

    – Leichtigkeitsrennen im Orbit

    11. Mai 2015 um 16:12 Uhr

  • Wie konntest du es versuchen cout in C?

    – Deanie

    11. Mai 2015 um 20:59 Uhr

  • @Daenie Ich habe printf verwendet, aber ich war zu faul, um C-Code einzufügen

    – omidh

    12. Mai 2015 um 4:23 Uhr

Wie ist das möglich, wenn das Programm einer Variablen immer einen freien Speicherplatz zuweist? Wie könnte es etwas statt Null sein?

Werfen wir einen Blick auf eine beispielhafte praktische Umsetzung.

Nehmen wir an, es verwendet Stack, um lokale Variablen zu behalten.

void
foo(void)
{
        int foo_var = 42;
}

void
bar(void)
{
        int bar_var;
        printf("%d\n", bar_var);
}

int
main(void)
{
        bar();
        foo();
        bar();
}

Völlig kaputter Code oben veranschaulicht den Punkt. Nachdem wir foo aufgerufen haben, wird eine bestimmte Position auf dem Stapel, an der foo_var platziert wurde, auf 42 gesetzt. Wenn wir bar aufrufen, belegt bar_var genau diese Position. Und tatsächlich führt die Ausführung des Codes zur Ausgabe von 0 und 42, was zeigt, dass man sich auf den bar_var-Wert nur verlassen kann, wenn er initialisiert wurde.

Jetzt sollte klar sein, dass eine lokale Variableninitialisierung erforderlich ist. Aber könnte hauptsächlich eine Ausnahme sein? Gibt es irgendetwas, das mit dem Stapel spielen und uns im Ergebnis einen Wert ungleich Null geben könnte?

Ja. main ist nicht die erste Funktion, die in Ihrem Programm ausgeführt wird. In der Tat gibt es Tonnen der Arbeit, die erforderlich ist, um alles einzurichten. Jede dieser Arbeiten hätte den Stack verwenden und einige Nicht-Nullen darauf hinterlassen können. Sie können nicht nur nicht den gleichen Wert auf verschiedenen Betriebssystemen erwarten, er kann sich sehr gut plötzlich auf genau dem System ändern, das Sie gerade verwenden. Interessenten können nach „Dynamic Linker“ googeln.

Schließlich kennt der C-Sprachstandard nicht einmal den Begriff Stack. Einen “Platz” für lokale Variablen zu haben, bleibt dem Compiler überlassen. Es könnte sogar zufälliger Mist von dem sein, was sich zufällig in einem bestimmten Register befindet. Es kann wirklich total sein irgendetwas. Wenn ein undefiniertes Verhalten ausgelöst wird, hat der Compiler tatsächlich die Freiheit zu tun, was er will.

  • “C-Sprachstandard” C ist nicht C++

    – Pharap

    21. April 2017 um 23:29 Uhr

  • Da dieses Beispiel undefiniertes Verhalten hervorruft, sollten Sie den genauen Compiler und die Compilereinstellung angeben, die Sie zum Reproduzieren des beobachteten Verhaltens verwendet haben.

    – Thomas Weller

    29. Januar 2021 um 15:40 Uhr

Wenn Sie eine Variable, die in einer Funktion definiert ist, nicht initialisieren, bleibt der Variablenwert undefiniert.

Dieses Bit ist wahr.

Das bedeutet, dass das Element den Wert annimmt, der sich zuvor an dieser Stelle im Speicher befand.

Dieses Bit ist es nicht.

In der Praxis wird dies manchmal vorkommen, und Sie sollten sich dessen bewusst sein Null bekommen oder nicht null bekommen passt perfekt zu dieser Theorie für jeden gegebenen Lauf Ihres Programms.

Theoretisch könnte Ihr Compiler dieser Ganzzahl tatsächlich einen zufälligen Anfangswert zuweisen, wenn er wollte, also ist es völlig sinnlos, dies zu rationalisieren. Aber machen wir weiter, als ob wir davon ausgegangen wären, dass “das Element den Wert annimmt, der sich zuvor an dieser Stelle im Speicher befand” …

Wie könnte es eher etwas als Null sein (ich gehe davon aus, dass der Standardwert für freien Speicher Null ist)?

Nun, das passiert, wenn Sie davon ausgehen. 🙂

  • Darüber hinaus entfernen einige Compiler möglicherweise den Speicherzugriff vollständig, in diesem Fall greifen Sie stattdessen auf Registerwerte zu.

    – yyny

    6. Dezember 2020 um 16:29 Uhr

Benutzer-Avatar
Gsamaras

Dieser Code ruft auf Undefiniertes Verhalten (UB), da die Variable nicht initialisiert verwendet wird.

Der Compiler sollte eine Warnung ausgeben, wenn ein Warnflag verwendet wird, wie z -Wall zum Beispiel:

warning: 'i' is used uninitialized in this function [-Wuninitialized]
  cout << i;
          ^

Es passiert einfach, dass es bei diesem Lauf auf Ihrem System den Wert 0 hatte. Das bedeutet, dass der Müllwert, dem die Variable zugewiesen wurde, zufällig 0 war, weil die Speicherreste dort dies nahelegten.

Beachten Sie jedoch, dass Kernel-Nullen relativ häufig auftreten. Das bedeutet, dass ich ziemlich häufig Null als Ausgabe meines Systems erhalten kann, aber es ist nicht garantiert und sollte nicht als Versprechen betrachtet werden.

  • Ich mag Ihre Erwähnung von Compiler-Flags wie -Wall

    – Hyäne

    3. Januar um 22:07 Uhr

Statische Variablen und globale Variablen werden auf Null initialisiert:

Global:
int a;  //a is initialized as 0

void myfunc(){
   static int x;     // x is also initialized as 0
   printf("%d", x);}

Wo als nicht statische Variablen oder Auto Variablen dh die lokalen Variablen sind unbestimmt (Unbestimmt bedeutet normalerweise, dass es alles tun kann. Es kann Null sein, es kann der Wert sein, der dort war, es kann das Programm zum Absturz bringen). Das Lesen vor dem Zuweisen eines Werts führt zu undefiniertem Verhalten.

void myfunc2(){
   int x;        // value of x is assigned by compiler it can even be 0
   printf("%d", x);}

Es hängt hauptsächlich vom Compiler ab, aber im Allgemeinen wird der Wert von den Compilern in den meisten Fällen als 0 angenommen

1013570cookie-checkNicht initialisiertes Variablenverhalten in C++

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy