it-swarm.com.de

Definieren einer Variablen und ihres statischen Äquivalents in derselben Funktion

Ich verstehe nicht, wie der folgende Code funktioniert:

#include "stdio.h"

int main(void) {
  int i = 3;
  while(i--) {
    static int i = 100;
    i--,
    printf("%d\n", i);
  }
  return 0;
}

Der mit Clang oder GCC kompilierte Code gibt die folgende Ausgabe aus:

99
98
97

Kann mir jemand erklären, was hier passiert? Es sieht so aus, als würden zwei Operationen in einer einzigen Anweisung und mehr als einmal ausgeführt. Ist es ein undefiniertes Verhalten? Ich beobachte dasselbe Verhalten in C++.

17
Xatyrian

Dies ist kein undefiniertes Verhalten.

#include "stdio.h"

int main(void) {
  int i = 3; //first i
  while(i--) {
    static int i = 100; //second i
    i--,
    printf("%d\n", i);
  }
  return 0;
}

Im while-Schleifenrumpf wird das lokaleste i (zweites i) bevorzugt. Beim Prüfen des Zustands in while-Schleife weiß er nicht, was sich im Körper befindet. Es ist also kein Problem, zuerst i zu wählen.

24
Pranit Kothari

Wikipedia sagt dazu sehr prominent:

Bei der Computerprogrammierung tritt die Variable shadowing auf, wenn eine in einem bestimmten Geltungsbereich (Entscheidungsblock, Methode oder innere Klasse) deklarierte Variable denselben Namen hat wie eine in einem äußeren Gültigkeitsbereich deklarierte Variable. Auf der Ebene der Bezeichner (Namen statt Variablen) wird dies als Namensmaskierung bezeichnet. Diese äußere Variable soll von der inneren Variablen abgeschattet werden, während der innere Bezeichner den äußeren Bezeichner maskiert. 

Jetzt hier im Block findet er die statische Variable und arbeitet darauf, aber die while-Bedingung verringert die Variable i, die außerhalb des Blocks deklariert ist. Der Geltungsbereich ist unterschiedlich - es ist kein Problem, den korrekten Wert von i zu verwenden. Dies ist gesetzlicher C-Code, aber nicht unbedingt eine gute Schreibweise. 

In der Tat gibt dies gcc -Wshadow progname.c

progname.c: In function 'main':
progname.c:7:20: warning: declaration of 'i' shadows a previous local [-Wshadow]
         static int i=2;
                    ^
progname.c:5:9: warning: shadowed declaration is here [-Wshadow]
     int i=2;
         ^

Aus dem Standard § 6.2.1p4

... Wenn ein Bezeichner zwei verschiedene Entitäten im selben Namensraum bezeichnet, können sich die Bereiche überlappen. Wenn ja, endet der Geltungsbereich einer Entität (der innere Gültigkeitsbereich) streng vor dem Gültigkeitsbereich der anderen Entität (des äußeren Gültigkeitsbereichs). Innerhalb des inneren Bereichs bezeichnet der Bezeichner die im inneren Bereich deklarierte Entität; die im äußeren Geltungsbereich deklarierte Entität ist innerhalb des inneren Geltungsbereichs verborgen (und nicht sichtbar).

11
coderredoc

Es ist möglich, eine gleichnamige Variable innerhalb eines verschachtelten Bereichs zu deklarieren. Der Compiler sieht sie als verschiedene Variablen. Es ist sehr verwirrend, aber die Variable, auf die Sie jedes Mal zugreifen, ist die im innersten Bereich deklarierte. Außerhalb von while ist es der int i = 3; und im Inneren der static int i = 100;

#include "stdio.h"

int main(void) {
  int i = 3; // outer i
  while(i--) { // outer i
    static int i = 100; // inner i
    i--, // inner i
    printf("%d\n", i); // inner i
  }
  return 0;
}

Wenn dies eine andere Funktion als main ist, würde der zweite Aufruf dazu führen 

96
95
94

und so weiter...

2
CIsForCookies