PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C, Variablen, Effekte


Kennung Eins
2024-06-11, 16:25:32
Wenn ich auf meinem Windows-System (VSCode, GCC) folgenden Code laufen lasse ...

#include<stdio.h>

int main()
{
int a;
printf("%i \n", a);
return 0;

}

Ausgabe: pseudo-zufällige Zahlen, je nach Zustand des reservierten Speichers.

... , dann bekomme ich für die Variable a unterschiedliche Werte (mir ist klar, weshalb).

Ich verstehe jedoch nicht, weshalb das nicht bei globalen Variablen funktioniert:

#include<stdio.h>

int a;

int main()
{
printf("%i \n", a);
return 0;

}

Ausgabe: 0


Kann mir das jemand erklären?

Trap
2024-06-11, 16:36:07
In C the use of any automatic variable before it has been initialized yields undefined behavior.

Was sagt gcc -Wextra ?

derF
2024-06-11, 16:38:50
Hier ist es genau so beschrieben, wie du es beobachtest:
https://en.cppreference.com/w/cpp/language/default_initialization

Exxtreme
2024-06-11, 16:44:12
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

Sektion 6.7.8:

If an object that has automatic storage duration is not initialized explicitly, its value is
indeterminate. If an object that has static storage duration is not initialized explicitly,
then:
— if it has pointer type, it is initialized to a null pointer;
— if it has arithmetic type, it is initialized to (positive or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules;
— if it is a union, the first named member is initialized (recursively) according to these rules.

Kennung Eins
2024-06-11, 16:46:36
Also per Definition 0.
Danke :)

[Edith]
Wobei mich jetzt interessiert, weshalb das bei den beiden Variabenarten so unterschiedlich ist.
Warum hat man das nicht einheitlich designed?

Exxtreme
2024-06-11, 16:55:01
Ich glaube, das liegt daran, dass bei globalen Variablen die Speicheradresse der Variable dem Compiler bekannt ist. Und die kann man dann direkt mit 0 initialisieren, ohne dass das zur Laufzeit Auswirkungen hat. Das ist bei Variablen, die im automatischen oder dynamischen Speicher liegen ist das nicht der Fall. Die Adresse wird da erst zur Laufzeit bekannt.

Asaraki
2024-06-11, 16:58:21
Ich glaube, das liegt daran, dass bei globalen Variablen die Speicheradresse der Variable dem Compiler bekannt ist. Und die kann man dann direkt mit 0 initialisieren, ohne dass das zur Laufzeit Auswirkungen hat. Das ist bei Variablen, die im automatischen oder dynamischen Speicher liegen ist das nicht der Fall. Die Adresse wird da erst zur Laufzeit bekannt.

This.
Heap vs Stack, wenn man sich bilden will

Sweepi
2024-06-11, 17:22:17
Globale und statische Variablen in C sind weder Teil des Heaps noch des Stacks, sondern von BSS.

https://upload.wikimedia.org/wikipedia/commons/5/50/Program_memory_layout.pdf
https://en.wikipedia.org/wiki/.bss#BSS_in_C

Kennung Eins
2024-06-11, 17:50:20
Ich glaube, das liegt daran, dass bei globalen Variablen die Speicheradresse der Variable dem Compiler bekannt ist. Und die kann man dann direkt mit 0 initialisieren, ohne dass das zur Laufzeit Auswirkungen hat. Das ist bei Variablen, die im automatischen oder dynamischen Speicher liegen ist das nicht der Fall. Die Adresse wird da erst zur Laufzeit bekannt.
Danke :)

Asaraki
2024-06-12, 17:43:36
Globale und statische Variablen in C sind weder Teil des Heaps noch des Stacks, sondern von BSS.

https://upload.wikimedia.org/wikipedia/commons/5/50/Program_memory_layout.pdf
https://en.wikipedia.org/wiki/.bss#BSS_in_C

Mea culpa, das war nicht direkt auf C bezogen. C muss ich höchstens mal lesen um ein vergessenes Legacyding zu verstehen. Da hab ich nie wirklich was entwickelt

Aber das ganze Konzept geht auf den heap und stack aus Fortran und co zurück, also welchen Speicher liest man wie, was wird vom System selbst initialisiert (respektive geprüft da dort oft ohne Kontrolle gelesen wurde)

Hilft imho schon zu verstehen, heute gibt es natürlich mehr als 2 Speicherbereiche, 4 in den meisten modernen, wobei ich längst den Überblick verloren habe ^ ^

Tldr : nicht aller Speicher wird gleich verwaltet/geprüft und man sollte wissen was in welchem Speicher liegt, zumindest grob

PHuV
2024-08-07, 23:25:42
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

— if it has arithmetic type, it is initialized to (positive or unsigned) zero;

Das war doch aber nicht immer so, oder? Wenn ich mich an meine C-Zeiten von den 80-90er erinnere, war das auch irgend ein random Wert. Wir hatten ab den 90ern Tools wie Rational Rose (später IBM) purify und quantify für Tests von Speicherlecks und uninitialisierten Variablen durchlaufen müssen (weil wir auch für 7 verschiedene Unix-Varianten + Windows entwickelten), und ich meinte, daß ein gobaler int sehr wohl angemoser wurde.