Lokale/ globale Variablen



  • Hallo! Gegeben sei folgendes Programmfragment:

    int a,b;
    ...                         (*1*)
    void x() {
       int x1;
    ...                         (*2*)
    }
    
    void y() {
       int y1,a,x1;
    ...                         (*3*)
      {
         int a,z;
         ...                    (*4*)
      }
    }
    ...                         (*5*)
    

    (i) Welche Variablen und welche Funktionen sind an den Punkten (*1*), (*2*), (*3*), (*4*) und (*5*) ansprechbar?

    (ii) Welche Variablen sind in der Funktion y global und welche lokal?

    ----

    Hier sind meine Antworten.

    Zu (i):

    \begin{array}{|c|c|c|} \mbox{Punkt} & \mbox{Variablen} & \mbox{Funktionen}\\ \hline (\*1\*) & a,b & -\\ (\*2\*) & a,b,x1 & -\\ (\*3\*) & a,b,y1,a,x1 & x\\ (\*4\*) & a,b,y1,a,x1,a,z & x\\ (\*5\*) & a,b & x,y \end{array}

    Zu (ii):

    Ist das ne Fangfrage?
    Ich hätte gesagt, dass alle Variablen lokal sind, weil sie doch alle im Rumpf der Funktion y sind. Höchstens würde ich noch sagen, dass a und z in dem innersten Block des Rumpfs der Funktion y noch lokaler sind, falls man das so sagen kann.

    Freue mich auf Eure Antworten!

    Beste Grüße

    LinuxC_newbie



  • An den Punkten 3 und 4 sind nicht alle a ansprechbar, sondern nur jeweils das innerste. Ansonsten sieht das so richtig aus (natürlich ist x1 in x etwas anderes als in y).

    Was ii angeht, so wird damit gemeint sein, dass b erreichbar und global ist (weil es außerhalb einer Funktion definiert wurde), während das globale a durch das lokale a verdeckt wird. An Punkt 4 ist a in der Tat noch lokaler, nämlich lokal im umgebenden Block.

    Ich finde es übrigens sehr schön, dass euer Material erwähnt, dass Blöcke freistehend (ohne if, while, for) sein und ihre eigenen Variablen beinhalten können. Das wird in so was häufig vergessen.



  • seldon schrieb:

    An den Punkten 3 und 4 sind nicht alle a ansprechbar, sondern nur jeweils das innerste.

    Wieso das? Das ist mir nicht klar.
    Könntest Du das evtl. erklären?


  • Mod

    (i):
    (*2*) ist falsch. Die Funktion x ist an der Stelle bekannt.
    (*3*) gleicher Fehler, die Funktion y ist bekannt. Außerdem vermute ich, dass der Lehrer etwas darüber hören will, wie man das globale a und das lokale a unterscheidet.
    (*4*) wieder fehlt y. Das lokale a aus Zeile 9 wird verdeckt und ist nicht ansprechbar.

    (ii): Auch ich finde die Frage komisch formuliert und weiß nicht, was erwartet wird. Jedenfalls gibt es immer noch die beiden Variablen a und b aus dem globalen Gültigkeitsbereich, die du erwähnen solltest.

    seldon schrieb:

    An den Punkten 3 und 4 sind nicht alle a ansprechbar

    Hier wird jetzt tatsächlich wichtig, ob der Lehrer C, C++ oder C mit cout/Klassen lehrt. So ganz sicher bin ich mir ja noch nicht und der TE weiß es laut dem anderen Thread selber nicht so genau.

    @Threadersteller: Du siehst ja selber, wo sich meine und seldons Korrektur unterschieden. Das ist einer der subtileren (und daher weniger bekannten) Unterschiede zwischen C und C++.



  • Hm,aber die Funktionen sind doch an den Stellen noch gar nicht formal "zu Ende", wie können sie da schon ansprechbar sein?



  • Sie müssen nicht "zu Ende" sein, sie müssen nur deklariert sein (=Es muss bekannt sein, dass es sie gibt, und wie sie aufgerufen werden).



  • Okay, danke. Dann hat sich das geklärt. 🙂



  • LinuxC_newbie schrieb:

    seldon schrieb:

    An den Punkten 3 und 4 sind nicht alle a ansprechbar, sondern nur jeweils das innerste.

    Wieso das? Das ist mir nicht klar.
    Könntest Du das evtl. erklären?

    Naja, wie willst du denn die äußeren beiden ansprechen? Wenn du an der Stelle

    a = 0;
    

    schreibst, ist das innerste gemeint. Der Name der anderen beiden ist dadurch verdeckt.

    ...wobei, ich glaube, an das globale kommst du mit

    ::a = 0;
    

    noch dran -- ich weiß jetzt nicht, ob das in der Aufgabe berücksichtigt wird. Aber du hast an Position 4 keine Chance, das a aus Zeile 9 anzusprechen, weil sein Name an der Stelle etwas anderes bezeichnet.

    Ansonsten hat SeppJ recht, das hab ich übersehen. Die Funktionsdeklaration endet quasi mit der Parameterliste, danach ist sie bekannt und kann verwendet werden - auch im eigenen Funktionskörper. Wenn ihr Rekursion noch nicht gehabt habt, wird das wahrscheinlich bald kommen; da braucht man das (bzw. hat es gerne).


  • Mod

    LinuxC_newbie schrieb:

    Hm,aber die Funktionen sind doch an den Stellen noch gar nicht formal "zu Ende", wie können sie da schon ansprechbar sein?

    Das ist nicht das Kriterium. Schließlich reicht schon eine Deklaration

    void foo();
    

    um eine Funktion foo() aufrufbar zu machen. Der Programmcode (= die Definition) der Funktion braucht dafür nicht vorhanden zu sein. Schließlich setzt der Compiler an an der Stelle des Funktionsaufrufes nur einen Funktionsaufruf :p ein, nicht den Maschinencode der Funktion selber. Dazu muss er bloß wissen, wie der Aufruf der Funktion lautet. Diese Information gibt ihm schon der Funktionskopf.

    Die Funktion selber kann auch in einer ganz anderen Datei definiert werden. Bloß am Ende beim Linken (wenn der Compiler lange fertig ist), wenn aus dem erzeugten Maschinencode ein ganzes Programm zusammengesetzt wird, dann muss der Linker zu jedem Funktionsaufruf den zugehörigen (vom Compiler erzeugten) Maschinencode finden können.

    (Obiges ist die einfache Erklärung. Wenn der Compiler den Funktionscode tatsächlich kennt, erzeugt er vielleicht gar nicht den Maschinencode zum Aufruf der Funktion, sondern setzt den Maschinencode der Funktion direkt an der Stelle ein (Inlining), wenn er das für schneller hält. Außerdem geht der Trend in den letzten Jahren zu neuen Optimierungstechniken, die den Maschinencode erst zur Linkzeit erzeugen (und der Compiler macht bloß eine Art Syntaxprüfung, anstatt Maschinencode zu erzeugen), damit dieses Inlining (und ein paar andere Techniken) häufiger angewandt werden können. Das alles ändert aber nichts daran, wann und wo du Funktionen aufrufen kannst. Der Absatz hier in den Klammern ist nur als Ausblick gedacht, wie das in Wirklichkeit technisch funktioniert. Die Beschreibung oben ist nämlich ziemlich idealisiert. Das war vielleicht vor 40 Jahren mal der Stand der Technik.)



  • Vielen, vielen Dank für die ganzen Erklärungen und Extrainfos!

    Ich möchte nochmal zum Abhaken zusammenfassen:

    Zu (i):

    (*1*):

    ansprechbare Variablen: a (Zeile 1), b (Zeile 1)
    ansprechbare Funktionen: keine

    (*2*):

    ansprechbare Variablen: a (Zeile 1), b (Zeile 1), x1 (Zeile 4)
    ansprechbare Funktionen: x

    (*3*):

    ansprechbare Variablen: globales a (Zeile 1), b (Zeile 1), y1 (Zeile 9), lokales a (Zeile 9), x1 (Zeile 9)
    ansprechbare Funktionen: x,y

    (*4*):

    ansprechbare Variablen: globales a (Zeile 1), b (Zeile 1), y1 (Zeile 9), x1 (Zeile 9), lokales a (Zeile 12), z (Zeile 12)

    WICHTIG: Nicht das lokale a aus Zeile 9!

    ansprechbare Funktionen: x,y

    (*5*):

    ansprechbare Variablen: globales a (Zeile 1), b (Zeile 1)
    ansprechbare Funktionen: x,y

    -------

    Zu (ii):

    b (Zeile 1) ist globale Variable von y
    Das globale a aus Zeile 1 ist verdeckt (zuerst in Zeile 9, dann dieses wiederum in Zeile 12)!

    y1, x1, a (alle Zeile 9) sind lokale Variablen von y, ebenso z (Zeile 12) und das lokale a in Zeile 12 ist gewissermaßen eine "noch lokalere" Variable von y.

    Ist das so nun eines "OKAY" würdig? 😃


  • Mod

    Ich möchte nochmal betonen, dass man an das globale a an den Punkten (*3*) und (*4*) nur mit Syntaxmitteln kommt (Scopeoperator :: ), die es nur in C++ gibt, nicht in C. Du warst dir heute Nachmittag ja nicht so sicher, was ihr überhaupt macht. In C wäre die Antwort entsprechend falsch, da an den Stellen das globale a nicht ansprechbar wäre.
    Ich glaube, dieser Punkt ging in der Diskussion etwas unter. Ist aber wichtig.

    Ansonsten sah deine letzte Version beim Überfliegen richtig aus.



  • Okay, dann schreibe ich bei (*3*) und (*4*) hinzu, dass man nur in C++ mit dem Scopeoperator auf das globale a aus Zeile 1 zugreifen kann, dass es "eigentlich" ja aber von dem jeweiligen lokalen a überdeckt ist.

    Nochmal allerbesten Dank, ich habe sehr viel gelernt.



  • b (Zeile 1) ist globale Variable von y

    b kann keine globale Variable von y sein.
    b ist einfach nur global und gehört gar nicht zu y.
    Es ist in y nur ansprechbar, was aber doch keinen Besitz/Zugehörigkeit ausdrückt.


Log in to reply