Peter: dynmische variablen in c++

Hallo,

Irgendwie hänge ich ein wenig. Was in PHP so einfach mit $$var geht scheint in c++ irgendwie nicht gar so einfach zu gehen. Ich will einen variablenname zusammenbauen und dann den inhalt aus dieser variable auslesen, geht das überhaupt ? Leider weiß ich nicht, wie so etwas auf "fachmännisch" heißt deshalb ist die Sache mit googel etwas schwer...

Danke und Gruss
 Peter

  1. Hi,

    kannst Du mal näher erläutern warum du das genau brauchst?
    Vielleicht kann man ja an dem Lösungsansatz etwas drehen.

    Ebos

    1. Hi,

      kannst Du mal näher erläutern warum du das genau brauchst?
      Vielleicht kann man ja an dem Lösungsansatz etwas drehen.

      Ebos

      Klaro, also es geht darum , daß ich ein paar Werte über Kommandozeile als Parameter einlese mit einer Klasse die das alles für mich übernimmt und mir entsprechend die Werte dann zu Verfügung stellt , die ich dann aber allesamt in einem array haben will zum sortieren...sprich die schleife sähe eben so aus
      for(int i=0;i<parameter_anzahl;i++){
        nummmern[i]=nummer_i

      }
       nummer_i soll dann eben der inhalt von nummer_1 bis nummer_x sein, weil so die variablen heißen die mir diese Kommandozeilen-klasse  liefert.

      Gruss
       Peter

      1. Moin!

        kannst Du mal näher erläutern warum du das genau brauchst?
        Vielleicht kann man ja an dem Lösungsansatz etwas drehen.

        Klaro, also es geht darum , daß ich ein paar Werte über Kommandozeile als Parameter einlese mit einer Klasse die das alles für mich übernimmt und mir entsprechend die Werte dann zu Verfügung stellt , die ich dann aber allesamt in einem array haben will zum sortieren...sprich die schleife sähe eben so aus
        for(int i=0;i<parameter_anzahl;i++){
          nummmern[i]=nummer_i

        }
        nummer_i soll dann eben der inhalt von nummer_1 bis nummer_x sein, weil so die variablen heißen die mir diese Kommandozeilen-klasse  liefert.

        Woher weiß dein Programm zur Übersetzungszeit, wie groß x ist, also wieviele nummer_i-Variablen angelegt werden sollen? Ich glaube, deine Kommandozeilen-Klasse möchte gerne die Parameter in einem std::vector speichern.

        Viele Grüße,
        Robert

  2. Hallo Peter,

    Irgendwie hänge ich ein wenig. Was in PHP so einfach mit $$var geht scheint in c++ irgendwie nicht gar so einfach zu gehen.

    Nein, das ist auch konzeptbedingt nicht möglich.

    Ich will einen variablenname zusammenbauen und dann den inhalt aus dieser variable auslesen, geht das überhaupt?

    Nein, denn in C/C++ existieren zur Laufzeit keine Variablennamen mehr. Der Code wird ja vom Compiler in reine Maschinensprache übersetzt, die Variablenbezüge werden damit auf Speicheradressen umgesetzt. Der Name der Variablen geht bei der Übersetzung komplett verloren und ist für die Ausführung des Programms auch nicht mehr erforderlich.

    Ich weiß auch noch nicht genau, was du mit diesem Konstrukt anstellen willst, aber vielleicht solltest du dich mit Zeigern anfreunden? Das könnte zumindest in die Richtung gehen.

    Schönen Tag noch,

    Martin

    --
    Wenn Zeit das Kostbarste ist, was wir haben, dann ist Zeitverschwendung die größte aller Verschwendungen.
      (Benjamin Franklin, amerikanischer Tüftler und Politiker)
    1. 你好 Der,

      Irgendwie hänge ich ein wenig. Was in PHP so einfach mit $$var geht
      scheint in c++ irgendwie nicht gar so einfach zu gehen.

      Nein, das ist auch konzeptbedingt nicht möglich.

      Das stimmt nicht ganz.

      Ich will einen variablenname zusammenbauen und dann den inhalt aus
      dieser variable auslesen, geht das überhaupt?

      Nein, denn in C/C++ existieren zur Laufzeit keine Variablennamen mehr.
      Der Code wird ja vom Compiler in reine Maschinensprache übersetzt, die
      Variablenbezüge werden damit auf Speicheradressen umgesetzt. Der Name
      der Variablen geht bei der Übersetzung komplett verloren und ist für
      die Ausführung des Programms auch nicht mehr erforderlich.

      Das ist nicht wahr. Übersetzt man eine Datei als „shared object“ (DLL unter
      Windows), muss und wird für globale Variablen in der Symbol-Tabelle ein
      Eintrag angelegt werden, damit eventuelle Zugriffe von Programmen auf diese
      Variable aufgelöst werden können. Unter Linux könnte man dann mit dem
      dynamischen Linker per dlsym() auf diese Variablen zugreifen. Ich nutze
      diese Technik für Plugins und Templates im CForum.

      再见,
       克里斯蒂安

      --
      Wenigstens gutes Toilettenpapier haben sie… | Block-Installation Nr. 5
      Ich bewundere wirklich den Sinn der Bienen für kollektive Verantwortung. Obwohl sich einzelne Bienen hin und wieder bekämpfen, herrscht zwischen Ihnen grundsätzlich ein starkes Gefühl für Eintracht und Zusammenarbeit. Wir Menschen gelten als sehr viel weiter entwickelt, doch mitunter rangieren wir sogar hinter kleinen Insekten.
      http://wwwtech.de/
      1. Hallo Christian,

        Nein, denn in C/C++ existieren zur Laufzeit keine Variablennamen mehr. Der Code wird ja vom Compiler in reine Maschinensprache übersetzt, die Variablenbezüge werden damit auf Speicheradressen umgesetzt. Der Name der Variablen geht bei der Übersetzung komplett verloren und ist für die Ausführung des Programms auch nicht mehr erforderlich.

        Das ist nicht wahr. Übersetzt man eine Datei als „shared object“ (DLL unter Windows), muss und wird für globale Variablen in der Symbol-Tabelle ein Eintrag angelegt werden, damit eventuelle Zugriffe von Programmen auf diese Variable aufgelöst werden können.

        Ja, richtig.
        Aber dann sprechen wir nicht mehr über programminterne Bezeichner, denn z.B. bei einer Windows-DLL ist der Name, unter dem eine Variable oder Funktion exportiert wird, nicht zwangläufig identisch mit dem Namen, den dasselbe Objekt auf Quelltextebene hatte. Ich kann den Linker anweisen, eine bestimmte Funktion in der Liste der exportierten Funktion ganz anders zu benamsen (macht man normalerweise nicht, weil's bequemer ist, die Funktionen von Anfang an "richtig" zu benennen). Ich kann den Linker auch anweisen, nur ausgewählte Funktionen/Variablen überhaupt zu exportieren.

        Wir haben also hier eine betriebssystemspezifische Schnittstelle zwischen verschiedenen Programmmodulen, die nicht auf jedem System überhaupt existieren muss und die auf einem gegebenen System (Linux, Windows) auch nicht von der verwendeten Programmiersprache C/C++ abhängig ist. Eine in Assembler/Delphi/VB geschriebene DLL hätte die gleiche Schnittstelle.

        Deswegen gilt dein Einwand nur für bestimmte Plattformen und selbst dann nur unter bestimmten Voraussetzungen..

        Unter Linux könnte man dann mit dem dynamischen Linker per dlsym() auf diese Variablen zugreifen. Ich nutze diese Technik für Plugins und Templates im CForum.

        Ja, unter Windows gibt es vergleichbare Möglichkeiten. Doch ich kann damit strenggenommen nicht auf die Bezeichner zugreifen, die im Quelltext verwendet wurden, sondern nur auf diejenigen, die der Linker bei der Erstellung der DLL zur Verfügung stellt, und das ist, wie gesagt, nicht unbedingt dasselbe.

        Schönen Abend noch,

        Martin

        --
        Was sagt die kleine Kerze zur großen Kerze?
        Ich gehe heute nacht aus!
        1. Hallo Martin,

          Wir haben also hier eine betriebssystemspezifische Schnittstelle zwischen verschiedenen Programmmodulen, die nicht auf jedem System überhaupt existieren muss und die auf einem gegebenen System (Linux, Windows) auch nicht von der verwendeten Programmiersprache C/C++ abhängig ist. Eine in Assembler/Delphi/VB geschriebene DLL hätte die gleiche Schnittstelle.

          Nicht zwangsläufig. Wenn ich (jetzt mal unter Linux, unter Windows ist's aber im Prinzip genauso) ein folgende Bibliothek habe:

          extern int testfunc (int a) {  
                  return a / 2;  
          }
          

          Das ist sowohl gültiges C als auch gültiges C++. Wenn ich das nun kompiliere:

          ------------------------------------------
          gcc -Wall -shared -o lib.so lib.c
          g++ -Wall -shared -o libxx.so libxx.cc
          ------------------------------------------

          (lib.c und libxx.cc sind identisch und enthalten den obigen Code; gcc ist der C-Compiler auf meinem System, g++ der C++-Compiler)

          Wenn ich mir nun die Symbole der beiden Bibliotheken ausgeben lassen, dann erhalte ich:

          ------------------------------------------
          christian@midnight ~/selfhtml/test $ strings libxx.so | grep testfunc
          _Z8testfunci
          christian@midnight ~/selfhtml/test $ strings lib.so | grep testfunc
          testfunc
          ------------------------------------------

          Im Falle der C++-Bibliothek werden also (da man C++-Bibliotheken Funktionen überladen kann, in C-Bibliotheken nicht) noch Typinformationen an den Funktionsnamen angehängt, im Fall der C-Bibliothek nicht. Wenn ich bei der C++-Bibliothek noch ein extern "C" { } drum rum mache, ist der Funktionsname wieder »testfunc« (und nicht »_Z8testfunci«).

          Die Schnittstelle, die eine Bibliothek besitzt, ist also auch von der Programmiersprache abhängig. Natürlich gibt es bestimmte Konventionen, die eine Bibliothek auf einem bestimmten Betriebsystem einhalten _muss_.

          Viele Grüße,
          Christian

          1. Hallo,

            [...] Eine in Assembler/Delphi/VB geschriebene DLL hätte die gleiche Schnittstelle.
            Nicht zwangsläufig.

            Äh, doch. *fingerhochzeig*
            Moooment. ;-)

            Im Falle der C++-Bibliothek werden also (da man C++-Bibliotheken Funktionen überladen kann, in C-Bibliotheken nicht) noch Typinformationen an den Funktionsnamen angehängt, im Fall der C-Bibliothek nicht.

            Ja, das ist richtig - wobei mir neu wäre, dass das mit dem Überladen zu tun hat, aber das lasse ich mal dahingestellt. Ich hatte nämlich bisher _gar_ keine Erklärung dafür. ;-)

            Die Schnittstelle, die eine Bibliothek besitzt, ist also auch von der Programmiersprache abhängig.

            Nein, die Schnittstelle ist vom Rest der Applikation und vom Betreibssystem abhängig, mit dem diese Applikation interagieren muss. Durch das "Name Mangling" sind die Bezeichner von C++ nicht mehr kompatibel mit denen von in anderen Sprachen geschriebenen Modulen. Deswegen muss man C++-Bezeichner, dier mit dem "Rest der Welt" gelinkt werden sollen, mit der Direktive extern "C" { ... } vom Name Mangling ausnehmen, damit sie wieder zum Schema passen (dasselbe gilt für externe Bezeichner, die man von C++ aus referenzieren möchte).

            Natürlich gibt es bestimmte Konventionen, die eine Bibliothek auf einem bestimmten Betriebsystem einhalten _muss_.

            Natürlich, und das Name Mangling ist eine Eigenheit von C++, die dessen Module von anderen unterscheidet. Insofern ist es eine sprachabhängige Geschichte - aber eigentlich nur eine Ausnahme von der Regel.

            Schönen Abend noch,

            Martin

            --
            Paradox ist, wenn jemand eingefleischter Vegetarier ist.
            Schon Urlaubspläne für 2006?
            1. Hallo Martin,

              Im Falle der C++-Bibliothek werden also (da man C++-Bibliotheken Funktionen überladen kann, in C-Bibliotheken nicht) noch Typinformationen an den Funktionsnamen angehängt, im Fall der C-Bibliothek nicht.

              Ja, das ist richtig - wobei mir neu wäre, dass das mit dem Überladen zu tun hat, aber das lasse ich mal dahingestellt. Ich hatte nämlich bisher _gar_ keine Erklärung dafür. ;-)

              Das ist die Erklärung, die ich kenne - und es ist auch die einzige, die wirklich sinnvoll ist. Die Forderung an ein Symbol in einer Bibliothek ist nämlich, dass dieses Symbol pro Bibliothek eindeutig sein muss (Ok, es ist nicht auf jedem Betriebsystem so, allerdings auf mindestens einem, auf dem C++ läuft) Wenn Du eine Funktion überlädst haben alle Varianten natürlich den gleichen Namen in der Programmiersprache - deswegen müssen die Symbole jedoch anders sein. Und selbst wenn das Betriebsystem mehrere Symbole mit dem gleichen Namen unterstützt - wie soll der Linker wissen, welches der Symbole zu welchem Prototypen passt?

              Viele Grüße,
              Christian

              1. n'Abend Christian,

                Ja, das ist richtig - wobei mir neu wäre, dass das mit dem Überladen zu tun hat, aber das lasse ich mal dahingestellt. Ich hatte nämlich bisher _gar_ keine Erklärung dafür. ;-)

                Das ist die Erklärung, die ich kenne - und es ist auch die einzige, die wirklich sinnvoll ist.

                je länger ich drüber nachdenke, desto sinnvoller erscheint sie mir auch. Ich hatte erst die Tragweite des "Überladens" nicht bedacht. Wenn eine Funktion, die in einem Modul definiert ist, einfach durch eine andere im Hauptmodul ersetzt werden soll, wäre so ein Aufwand sicher unsinnig. Aber das Konzept des Überladens in C++ ermöglicht ja auch die mehrfache Definition gleichnamiger Funktionen mit unterschiedlichen Parameterlisten.

                Wenn Du eine Funktion überlädst haben alle Varianten natürlich den gleichen Namen in der Programmiersprache - deswegen müssen die Symbole jedoch anders sein.

                Das ist es wahrscheinlich, was du mit diesem Satz ausdrücken wolltest. Ja, bei Licht besehen ist es die einzige halbwegs kompatible Möglichkeit.

                Und selbst wenn das Betriebsystem mehrere Symbole mit dem gleichen Namen unterstützt - wie soll der Linker wissen, welches der Symbole zu welchem Prototypen passt?

                Richtig. :-)

                Schönen Abend noch,

                Martin

                --
                Wissen erwirbt man, indem man immer das Kleingedruckte sorgfältig liest.
                Erfahrung bekommt man, indem man das nicht tut.
        2. Moin!

          Wir haben also hier eine betriebssystemspezifische Schnittstelle zwischen verschiedenen Programmmodulen, die nicht auf jedem System überhaupt existieren muss und die auf einem gegebenen System (Linux, Windows) auch nicht von der verwendeten Programmiersprache C/C++ abhängig ist. Eine in Assembler/Delphi/VB geschriebene DLL hätte die gleiche Schnittstelle.

          Inwiefern spielt denn an dieser Stelle die sogenannte Calling-Convention eine Rolle? Aus meinen Tagen der Windows-Programmierung sowohl mit C als auch Delphi kenne ich, dass C-Funktionen standardmäßig als „cdecl“ betrachtet werden, d.h. die Argumente an die Funktion werden in einer bestimmten Reihenfolge auf den Stack gelegt, so dass C-Funktionen eine variable Anzahl an Argumenten entgegennehmen können. Außerdem ist die C-Funktion selbst dafür verantwortlich, beim Rücksprung den Stack in einem ordentlichen Zustand zu hinterlassen. Delphi-Funktionen hingegen sind standardmäßig “pascal“, d.h. es kann nur eine bestimmte Zahl an Parametern übergeben werden und der Stack wird nicht von der Funktion aufgeräumt, sondern von … irgendjemand anderem. Beim Einbinden einer Bibliothek muss man im Quellcode immer angegeben, nach welcher Calling-Convention die entsprechenden Symbole aufgelöst werden sollen.

          Viele Grüße,
          Robert

          1. Moin Robert,

            Wir haben also hier eine betriebssystemspezifische Schnittstelle zwischen verschiedenen Programmmodulen, die nicht auf jedem System überhaupt existieren muss und die auf einem gegebenen System (Linux, Windows) auch nicht von der verwendeten Programmiersprache C/C++ abhängig ist. Eine in Assembler/Delphi/VB geschriebene DLL hätte die gleiche Schnittstelle.
            Inwiefern spielt denn an dieser Stelle die sogenannte Calling-Convention eine Rolle?

            Sie spielt eine große Rolle für die Kompatibilität verschiedener Module untereinander, hat aber nichts mit den _Namen_ der Funktionen zu tun. Für ein gegebenes System muss aber diese "Calling Convention" ebenso eingehalten werden, logisch.

            Aus meinen Tagen der Windows-Programmierung sowohl mit C als auch Delphi kenne ich, dass C-Funktionen standardmäßig als „cdecl“ betrachtet werden, d.h. die Argumente an die Funktion werden in einer bestimmten Reihenfolge auf den Stack gelegt, so dass C-Funktionen eine variable Anzahl an Argumenten entgegennehmen können. Außerdem ist die C-Funktion selbst dafür verantwortlich, beim Rücksprung den Stack in einem ordentlichen Zustand zu hinterlassen.

            Nee, gerade andersrum: Nach cdecl ist die _übergeordnete_ Funktion für das Abräumen des Stacks nach dem Funktionsaufruf zuständig. Die aufgerufene Funktion kann dies nicht, da sie nicht "weiß", wieviele Argumente ihr übergeben wurden. Mit "pascal" deklarierte Funktionen tun das selber.
            Der andere wichtige Unterschied ist die Reihenfolge der Parameter, wie du richtig bemerkt hast: Bei "cdecl" wird die Parameterliste von rechts nach links abgearbeitet, der erste Parameter kommt also zuletzt auf den Stack; bei "pascal" dagegen von links nach rechts, in normaler Leserichtung.

            Schönen Tag noch,

            Martin

            --
            Wichtig ist, was hinten rauskommt.
              (Helmut Kohl, 16 Jahre Bundeskanzler)
            1. Moin!

              Aus meinen Tagen der Windows-Programmierung sowohl mit C als auch Delphi kenne ich, dass C-Funktionen standardmäßig als „cdecl“ betrachtet werden, d.h. die Argumente an die Funktion werden in einer bestimmten Reihenfolge auf den Stack gelegt, so dass C-Funktionen eine variable Anzahl an Argumenten entgegennehmen können. Außerdem ist die C-Funktion selbst dafür verantwortlich, beim Rücksprung den Stack in einem ordentlichen Zustand zu hinterlassen.

              Nee, gerade andersrum: Nach cdecl ist die _übergeordnete_ Funktion für das Abräumen des Stacks nach dem Funktionsaufruf zuständig. Die aufgerufene Funktion kann dies nicht, da sie nicht "weiß", wieviele Argumente ihr übergeben wurden. Mit "pascal" deklarierte Funktionen tun das selber.

              Stimmt, das kann man sich mit solchen C-Funktionen wie [link:http://www.freebsd.org/cgi/man.cgi?query=printf&apropos=0&sektion=3&manpath=deutsch+-+Linux%2FGNU&format=html@title=printf](const char *format, ...) gut merken.

              Der andere wichtige Unterschied ist die Reihenfolge der Parameter, wie du richtig bemerkt hast: Bei "cdecl" wird die Parameterliste von rechts nach links abgearbeitet, der erste Parameter kommt also zuletzt auf den Stack;

              Das ermöglicht dann auch die variable Anzahl an Argumenten, wobei ich der Funktion einen festen Parameter als erstes übergeben muss (im Fall von printf ist dies format), der als erstes in meiner Funktion landet, damit die Funktion darauf schließen kann, wieviele Parameter folgen.

              bei "pascal" dagegen von links nach rechts, in normaler Leserichtung.

              Deshalb haben Pascal-Funktionen eine feste Anzahl an Argumenten.

              Danke für die Erklärung, jetzt habe ich endlich einmal verstanden, was es damit auf sich hat!

              Viele Grüße,
              Robert