Forum: PC-Programmierung static int nur einmal initialisieren?


von Tom L. (xedux)


Lesenswert?

Moin,


code:
int zaehlen() {
  static int counter = 0;
  return ++counter;
}

int main() {
  printf("Zaehler: %d\n", zaehlen());
  printf("Zaehler: %d\n", zaehlen());
  printf("Zaehler: %d\n", zaehlen());
  return 0;
}


die Ausgabe:

Zaehler: 1
Zaehler: 2
Zaehler: 3

mir ist nicht ganz klar, warum die Ausgabe so aussieht wie sie 
aussieht..
Wird nicht jedesmal wenn die Funktion zaehlen aufgerufen wird die 
Variable counter neu mit 0 initialisiert? Demnach müsste die Ausgabe 
doch

Zaehler: 1
Zaehler: 1
Zaehler: 1

..sein, oder nicht?

Kann mir das so frueh am Morgen schon jemand klar machen? :)

von (prx) A. K. (prx)


Lesenswert?

Eine Initialisierung ist keine Zuweisung. Der Inhalt wird am Anfang der 
Lebensdauer der Variablen initialisiert.

von Mr Bean (Gast)


Lesenswert?

Les im Internet mal nach was eine static Variable macht...
Danke das sollte reichen.

Gruß

Bean

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Die Initialisierung geschieht bereits vor main im Startup-Code.

Das "= 0" ist übrigens redundant, da Variablem im Static Storage, die 
keinen Initializer haben, immer mit 0 initialisiert werden — auch wenn 
sie lokal sind.

von Peter II (Gast)


Lesenswert?

Johann L. schrieb:
> Die Initialisierung geschieht bereits vor main im Startup-Code.

aber nur bei C, bei C++ wird es später gemacht.

von (prx) A. K. (prx)


Lesenswert?

Nein.

von Tom L. (xedux)


Lesenswert?

Also ich denke, wenn ich die Variable mit  = 0 initialisiere, dann wird 
ihr der Wert 0 zugewiesen.. was auch definitiv so ist. hab das =0 mal 
weggelassen, dann stehen da irgendwelche Werte drin.
Wenn ich die Variable nicht als static deklariere aber mit 0 
initialisiere, dann ist die Ausgabe immer 1, wie ich das eben dachte.

...doch nicht... sorry. das =0 scheint tatsächlich redundant zu sein.
Jetzt stört mich nur noch, dass einer nicht static Variablen die 0 immer 
wieder zugewiesen wird, bei der static allerdings nicht.
Es scheint also so zu sein, dass static Variablen nur einmal 
Initialisiert werden können..

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Tom L. schrieb:
> Es scheint also so zu sein, dass static Variablen nur einmal
> Initialisiert werden können..

Genau so ist es... was "stört" dich daran? Niemand zwingt dich sie 
"static" zu machen wenn dir das Verhalten nicht gefällt.

von (prx) A. K. (prx)


Lesenswert?

Vielleicht solltest du doch mal in den sauren Apfel beissen und ein C 
Buch besorgen, oder entsprechende Webseiten lesen.

von Tom L. (xedux)


Lesenswert?

A. K. schrieb:
> Vielleicht solltest du doch mal in den sauren Apfel beissen und ein C
> Buch besorgen, oder entsprechende Webseiten lesen.

tu ich doch gerade :D in dem Tutorial wird nicht explizit auf meine 
Frage eingegangen.. und da ich weiß, dass hier ab und an mal jemand 
hilfsbereites am Start ist und es auch schneller geht hier eine Antwort 
zu bekommen als im WWW hab ich diesen Weg gewählt. Fertige Texte kann 
man nix fragen..

Und stören tut mich an dem Verhalten nix, wollte nur wissen warum sich 
sone static anders verhält als eine nicht static. Brauchen tu ich sie 
momentan gar nicht. Ich versuche gerade C zu lernen. ;)

von Tom L. (xedux)


Lesenswert?

Läubi .. schrieb:
> Tom L. schrieb:
>> Es scheint also so zu sein, dass static Variablen nur einmal
>> Initialisiert werden können..
>
> Genau so ist es... was "stört" dich daran? Niemand zwingt dich sie
> "static" zu machen wenn dir das Verhalten nicht gefällt.

Das Verhalten ist in dem code ja gerade genau so erwünscht.. wollte nur 
wissen wieso das so ist :). Aber ich kann erstmal damit leben, dass 
statics eben nur einmal initialisiert werden, im Gültigkeitsbereich

von W7 (Gast)


Lesenswert?

A. K. (prx) schrieb:

> Vielleicht solltest du doch mal in den sauren Apfel beissen und ein C
> Buch besorgen, oder entsprechende Webseiten lesen.

Da isser nicht der einzige mit dieser Verhaltensweise. Andere fragen dem 
halben Forum Löcher in den Bauch, was sie denn jetzt für 'ne 
Programmiersprache lernen sollten, anstatt sich mal selber mit den 
elementarsten Eigenarten der einzelnen Richtungen zu beschäftigen.

;)

von Tom L. (xedux)


Lesenswert?

W7 schrieb:
> A. K. (prx) schrieb:
>
>> Vielleicht solltest du doch mal in den sauren Apfel beissen und ein C
>> Buch besorgen, oder entsprechende Webseiten lesen.
>
> Da isser nicht der einzige mit dieser Verhaltensweise. Andere fragen dem
> halben Forum Löcher in den Bauch, was sie denn jetzt für 'ne
> Programmiersprache lernen sollten, anstatt sich mal selber mit den
> elementarsten Eigenarten der einzelnen Richtungen zu beschäftigen.
>
> ;)

Wenn das wirklich falsch wäre, würde hier niemand irgendwas fragen 
dürfen.
Ich denke schon, dass das Forum dafür nutzbar sein sollte. Aber darum 
geht es hier nicht.. Wen solche Fragen stören, der kann sie ja 
ignorieren. Oder ein Moderator gibt mir mal den hinweis, dass meine 
Frage zu "lowleveled" ist und ich mich bitte um anderweitige Lösung 
bemühen soll... ;)

Danke

von W7 (Gast)


Lesenswert?

Tom L. (xedux) schrieb:

> .. Oder ein Moderator gibt mir mal den hinweis, dass meine
> Frage zu "lowleveled" ist und ich mich bitte um anderweitige Lösung
> bemühen soll... ;)

Das kann schneller passieren als man denkt. ;-)

Beitrag "Re: Variable zu ASCII umwandeln in C"

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Tom L. schrieb:

> Das Verhalten ist in dem code ja gerade genau so erwünscht.. wollte nur
> wissen wieso das so ist :)

Ei weil die Funktion / Variable so ein "Gedächtnis" hat, was bei 
nicht-statischen Variablen eben nicht so ist.  Das kann vor und 
Nachteile haben, und ja nach Anwendungsfall wird man Speicherklasse 
static oder auto wählen.

static: Gedächtnis, die Funktion kann einen Status über mehrere Aufrufe 
behalten.

auto: Die Funktion ist reentrand, der Platz wird nicht statisch belegt 
(was wieder Vor- und nachteile haben kann)

malloc: Lebensdauer der Variablen ist unbekannt bzw. geht nicht einher 
mit einem C-Block / einer C-Funktion (dann ginge alloca oder lokale 
(statische) Variable), schlecht oder nicht statisch analysierbar

von Yalu X. (yalu) (Moderator)


Lesenswert?

Die Lebensdauer einer Static-Variable reicht vom Programmbeginn bis zum
Programmende. Sie wird also innerhalb eines Programmlaufs genau einmal
angelegt und genau einmal wieder zerstört. Das Gleiche gilt auch für
globale Variablen.

Die Lebensdauer einer Auto-Variable (also einer die innerhalb eines
Blocks, aber nicht als static definiert wird) reicht von ihrer
Definition bis zum Blockende. Jeder Block kann aber innerhalb eines
Programmlaufs mehrmals durchlaufen werden. Deswegen hat so eine Variable
sozusagen mehrere Leben.

Jetzt schau dir noch einmal die Aussage von A. K. an:

A. K. schrieb:
> Der Inhalt wird am Anfang der Lebensdauer der Variablen initialisiert.

Ist's jetzt etwas klarer?

von Tom L. (xedux)


Lesenswert?

jupp... leuchtet ein, dankeschön! :)

von DirkB (Gast)


Lesenswert?

Tom L. schrieb:
> Das Verhalten ist in dem code ja gerade genau so erwünscht.. wollte nur
> wissen wieso das so ist :). Aber ich kann erstmal damit leben, dass
> statics eben nur einmal initialisiert werden, im Gültigkeitsbereich

Die "Erfinder von C" haben sich auch etwas dabei gedacht.
Was bringt dir eine static-Variable, wenn sie bei jedem Funktionsaufruf 
wieder auf einen festen Wert gesetzt wird?
Nichts.

von Tom L. (xedux)


Lesenswert?

mich hat ja nur verwirrt, warum der Befehl: static int counter = 0;
die Variable counter nicht wieder auf 0 gesetzt hat, bei jedem 
Funktionsaufruf, da diese Zuweisung ja im Funktionsblock steht und somit 
bei jedem Durchlauf wieder neu auf 0 gesetzt werden müsste. Das ist aber 
nur bei "nicht static" Variablen so, wenn ich das gerade richtig 
verstanden hab, bzw. static Variablen lassen sich nur einmal 
initialisieren/zuweisen.

von Karl H. (kbuchegg)


Lesenswert?

Tom L. schrieb:
> mich hat ja nur verwirrt, warum der Befehl: static int counter = 0;
> die Variable counter nicht wieder auf 0 gesetzt hat, bei jedem
> Funktionsaufruf, da diese Zuweisung ja im Funktionsblock steht

Nochmal. Das ist nämlich wichtig.

DAS IST KEINE ZUWEISUNG! (Selbst wenn da ein = geschrieben steht)

Das ist eine Initialisierung.
Und initialisiert werden kann immer nur EINMAL!
Egal welche Variable. Wenn sie überhaupt initialisiert wird (lokale 
nicht statische Variablen werden per Default nicht initialisiert) dann 
geschieht das ganz am Anfang ihrer Lebensdauer. Sozusagen wenn sie zur 
Welt kommt. Immer. Egal welche Variable. Diese Regelung ist für alle 
Variablen gleich. WEnn sie initialisiert wird, dann geschieht das 
ausschliesslich und nur an dem Zeitpunkt, an dem die Variable 
tatsächlich erzeugt wird.

> verstanden hab, bzw. static Variablen lassen sich nur einmal
> initialisieren/zuweisen.

Alle Variablen werden nur EINMAL initialisiert (wenn überhaupt).
Da liegt der springende Punkt.

In C ist das noch nicht soooo wichtig. Aber in C++ ist die 
Unterscheidung zwischen Initialisierung und Zuweisung ein essentiell 
wichtiger Punkt, wenn auch die Regeln an dieser Stelle in diesem 
Hinblick absolut identisch sind! Aber in C++ hängt einfach nur noch mehr 
an dieser Unterscheidung in Form von Folgerungen drann. Das ist alles.
Initialisiert wird eine Variable dann, wenn sie umgangssprachlich 
geboren wird. Alles danach kann dann nur noch eine Zuweisung sein.


d.h. zwischen

   int j = 5;

und

   int k;
   k = 5;

gibt es einen essentiell wichtigen Unterschied!
Das erste ist eine Initalisierung. Dies deshalb, weil die Angabe bei der 
Variablendefinition steht. Deshalb ist
    int j = 5;
eine Initialisierung. Mittels
    int j ....
wird eine neue Variable erzeugt (definiert). Und mittels
    ..... = 5
wird festgelegt, wie diese Variable im Zuge dieser Erzeugung zu 
initialisieren ist.

Wohingegen im 2.tem Fall eine uninitialisierte Variable k erzeugt wird 
(die natürlich auch einen Wert hat, irgendeinen Wert haben Variablen 
immer, aber eben keinen definierten, da uninitialisiert), die dann im 
2.ten Schritt mit einer Zuweisung auf den Wert 5 gesetzt wird. Hier ist 
also
     k = 5;
tatsächlich eine Zuweisung.

Und ja. So gesehen hat das = 2 Bedeutungen und ist nicht automatische 
immer eine Zuweisung.

von Tom L. (xedux)


Lesenswert?

wenn ich den code also so ausführe:

int zaehlen() {
  static int counter = 0;
  return ++counter;
}

int main() {
  printf("Zaehler: %d\n", zaehlen());
  printf("Zaehler: %d\n", zaehlen());
  printf("Zaehler: %d\n", zaehlen());
  return 0;
}

wird static int counter nur einmal initialisiert, weil das generell nur 
einmal geht (geboren werden). Sie erhält den Wert 0. Für den weiteren 
Ablauf des Programms hat die Zeile: static int counter = 0; also keine 
Bedeutung mehr?

Wenn ich den code so ausführe: (also ohne static)

int zaehlen() {
  int counter = 0;
  return ++counter;
}

int main() {
  printf("Zaehler: %d\n", zaehlen());
  printf("Zaehler: %d\n", zaehlen());
  printf("Zaehler: %d\n", zaehlen());
  return 0;
}


..hat die Zeile Bedeutung für den weiteren Ablauf.. counter wird bei 
jedem Durchlauf "auf 0 gesetzt". Würde also in deiner Denke bedeuten, 
dass sie einmal initialisiert wird mit 0 und danach, je nach dem wie oft 
die Schleife läuft, den Wert 0 zugewiesen bekommt? eine neue 
Initialisierung gibts ja nicht, sagst Du. Ist das so? Und wenn JEDE 
Variable nur EINMAL initialisiert werden kann, warum wird dann immernoch 
die int counter neu "zugewiesen" und die static int counter nicht? Warum 
ignoriert die static Variable die Zeile static int counter = 0; bei 
jedem weiteren SchjleifendurchlauF?

von Yalu X. (yalu) (Moderator)


Lesenswert?

Tom L. schrieb:
> Würde also in deiner Denke bedeuten, dass sie einmal initialisiert
> wird mit 0 und danach, je nach dem wie oft die Schleife läuft, den
> Wert 0 zugewiesen bekommt?

Nein, die Variable wird jedesmal initialisiert, weil sie in jedem
Aufruf von zaehlen() neu angelegt wird, denn beim Verlassen der Funktion
verschwindet sie wieder. Wenn man's genauer betrachtet, ist counter also
in jedem neuen Funktionsaufruf eine andere Variable, die lediglich den
gleichen Namen hat wie die Variable aus dem vorangegangenen Aufruf. Die
jeweils neu angelegte Variable kann am gleichen Speicherplatz liegen
wie die alte, muss es aber nicht.

Ist counter hingegen als static deklariert, bleibt die Variable bei
jedem Aufruf dieselbe. Sie verschwindet auch nicht zwischen zwei
Funktionsaufrufen, lediglich ihr Name "counter" existiert außerhalb der
Funktion nicht.

von Tom M. (Gast)


Lesenswert?

Tom L. schrieb:
> int zaehlen() {
>   static int counter = 0;
>   return ++counter;
> }

static Variablen werden genau 1 (ein) Mal zur Laufzeit des Programms 
angelegt. counter liegt nicht im Stack Frame der Funktion zaehlen, 
sondern der Speicherplatz wird (tadaa) statisch, fix reserviert. 
counter ist immer da, aber der Compiler erlaubt nur der Funktion 
zaehlen Zugriff darauf.

Tom L. schrieb:
> int zaehlen() {
>   int counter = 0;
>   return ++counter;
> }

counter wird bei jedem Einsprung in die Funktion zaehlen neu erzeugt 
(auf dem Stack) und bei Verlassen der Funktion wieder vernichtet.

von Tom L. (xedux)


Lesenswert?

aah.. ok, es klart auf :)

von Tom L. (xedux)


Lesenswert?

das war das was ich nicht verstanden hab.. nun ist es einleuchtend.
Danke!
Das heißt dann also, es ist Unsinn dass "nonstatic" Variablen nur einmal 
initialisiert werden... wobei nee das is kein Unsinn. Initialisiert 
werden sie ja nur einmal.. dann halt immer ne neue counter Variable.. 
und deshalb wird sie auch immer neu mit 0 initialisiert, wohingegen die 
static Variable fest im Speicher liegt und nicht neu 
angelegt/initialisiert wird, weil sie als static markiert ist.?

von Karl H. (kbuchegg)


Lesenswert?

Tom L. schrieb:
> das war das was ich nicht verstanden hab.. nun ist es einleuchtend.
> Danke!
> Das heißt dann also, es ist Unsinn dass "nonstatic" Variablen nur einmal
> initialisiert werden... wobei nee das is kein Unsinn. Initialisiert
> werden sie ja nur einmal.. dann halt immer ne neue counter Variable..
> und deshalb wird sie auch immer neu mit 0 initialisiert, wohingegen die
> static Variable fest im Speicher liegt und nicht neu
> angelegt/initialisiert wird, weil sie als static markiert ist.?


Genau.
Und es ist deswegen kein (genereller) Unsinn, lokale Variablen zu 
initialisieren, denn wenn du sie nicht initialisierst, dann haben sie 
irgendeinen Wert. Erinnere dich daran: lokale, nicht statische Variablen 
werden per Default überhaupt nicht initialisiert.

In
1
void foo()
2
{
3
  int i;
4
5
  ...
6
}

ist nicht klar, welchen Wert i nach seiner Geburt (nach Betreten der 
Funktion) hat. Das kann 0 sein, das kann aber auch jeder andere 
beliebige Wert sein. Was eben gerade zufällig die Bits im Speicher für 
einen Wert hatten. Mit einer Initialisierung hingegen
1
void foo()
2
{
3
  int i = 0;
4
5
  ...
6
}

kannst du dich darauf verlassen, dass i nach seiner Geburt garantiert 
den Wert 0 hat. Das mag für dich wichtig sein, wenn es das nicht ist, 
dann kann man die Inisitlisierung auch weglassen. hier zb
1
void foo()
2
{
3
  int i;
4
5
  for( i = 0; i < 8; i++ )
6
    ...
7
}

ist es nicht wichtig, dass i nach seiner Geburt einen definierten Wert 
hat, denn im Zuge des for bekommt es sowieso dann einen ersten 
definierten Wert zugewiesen. Hier ist eine Initialisierung von i daher 
nicht wichtig. Sie würde aber (ausser ein bischen zusätzlicher 
Programmlaufzeit) auch nicht schaden.

Und wie schon gesagt:
In dem Moment, in dem der Rücksprung aus der Funktion zum Aufrufer 
zurück erfolgt, werden alle lokalen, nicht statischen Variablen 
zerstört. So als ob sie nie existiert hätten.

Bei static geht es also nicht im eigentlichen Sinn um Initialisierung 
oder nicht. Bei static bzw. nicht static geht es (an dieser Stelle, 
static hat auch noch eine 2.te Bedeutung) um die Lebensdauer von 
Variablen in Funktionen! Die Sache mit der Initialisierung ist nur eine 
logische Folgerung aus dieser Lebensdauer und dem Grundsatz 
"initialisiert wird nur einmal"

von Tom L. (xedux)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Und wie schon gesagt:
> In dem Moment, in dem der Rücksprung aus der Funktion zum Aufrufer
> zurück erfolgt, werden alle lokalen, nicht statischen Variablen
> zerstört. So als ob sie nie existiert hätten.
>
> Bei static geht es also nicht im eigentlichen Sinn um Initialisierung
> oder nicht. Bei static bzw. nicht static geht es (an dieser Stelle,
> static hat auch noch eine 2.te Bedeutung) um die Lebensdauer von
> Variablen in Funktionen! Die Sache mit der Initialisierung ist nur eine
> logische Folgerung aus dieser Lebensdauer und dem Grundsatz
> "initialisiert wird nur einmal"

jo, nu hab ichs :) danke nochmal

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.