Variblen in Makros definieren



  • Hallo,

    ich habe ein C++ - Programm, in dem ich Variablen in Makros definiere. Hier mal vereinfacht das Problem:

    #define DEF(name) int name
    
    ...
    
    DEF(A);
    DEF(B);
    
    A = 1;
    

    Wenn ich aber auf diese Variablen zugreifen will, dann sagt mir der Compiler, dass diese Variablen noch nicht definiert worden sind...
    Wie kann ich das umgehen?


  • Mod

    Das funktioniert so. Zeig mehr Code, dein Fehler ist ein anderer.



  • ich bin auch der Meinung, dass es so funktionieren muss.

    es sei denn du machst da bei ... was falsch



  • Hallo,

    danke für die schnellen Antworten 👍.
    Also hier mein Programm. Ich muss leider neun Tabellen einlesen die alle unterschiedliche Größen haben. Die ersten beiden Einträge geben immer an, wie viele Zeilen und Spalten die Tabelle hat. Wenn ich dann die Größe kenne, definiere ich mir passende Arrays und speichere die Einträge darin ab. Um es etwas abzukürzen, wollte ich eben ein Makro für alle neun Tabellen schreiben. (Wie kann ich eigentlich im Makro Zeilenumbrüche einbauen?)

    #include<iostream>
    #include<string>
    #include<fstream>
    #define READ_M(M, name) {ifstream data (name); data >> rows >> cols; float M [rows][cols]; for (int I = 0; I < rows; I++) { for (int J = 0; J < rows; J++) { data >> M [I] [J]; } } data.close(); }
    
    using namespace std;
    
    int main(int argc, char*argv[])
    {
      if (argc!=2)
        {
          cout << "Usage: FVM <directory_grid>" << endl;
          exit(0);
        }
      char *directory = argv[1];
      chdir (directory);
    
      int rows, cols;
      READ_M(xp, "xp.txt");
      // uvm...
    
      xp[1][1] = 0;
    
      return 0;
    }
    

    g++ liefert mir dann die Fehlermeldung:
    Fehler: »xp« wurde in diesem Gültigkeitsbereich nicht definiert

    Viele Grüße,
    Kruemel



  • C++ kennt kein VLA (Variable-length array).
    Nimm stattdessen ein boost::multiarray.



  • Ausserdem musst du die {}-Umklammerung entfernen, falls das funktionieren soll.



  • Ich merke gerade, dass zwei Schleifen über die Anzahl der Zeilen laufen, das sollte ich mal ändern 🙄
    In meinem Fall war die Tabelle xp.txt aber quadratisch...


  • Administrator

    Die Fehlermeldung ist auch korrekt. Dein Makro öffnet und schliesst auch noch einen Block. Die Variable xp ist nur in diesem Block definiert, aber nicht ausserhalb.
    Ich begreife aber nicht, wieso du dazu ein Makro schreiben musst. Eine normale Funktion hätte es auch getan. Allerdings versteht C++ keine Variablelength Arrays, welche du benutzt. Nimm doch stattdessen einfach einen std::vector , welcher in einer normalen Funktion befüllt wird.

    Grüssli



  • Warum benutzt du ein Makro statt ner Funktion?



  • VLA_dimir schrieb:

    Ausserdem musst du die {}-Umklammerung entfernen, falls das funktionieren soll.

    Nö. Doch. 🤡



  • VLA_dimir und Dravere, Ihr habt Recht, ohne { } funktioniert es, danke!
    Ich dachte mit einer Funktion kann man nicht aus einem Übergabeparameter eine Variable erstellen... Das sollte ich aber mal ausprobieren.

    Über std::vector habe ich auch schon nachgedacht. Da ich aber bei den Berechnungen die Matrixgrößen nicht mehr verändere, hab ich doch die ollen Arrays genommen.



  • Meinst du wirklich, ein Funktionsaufruf macht bei hunderten von data.operator>>()-Aufrufen etwas aus?
    Du kannst es ja inline deklarieren, wenn du tatsächlich meinst, es sei entscheidend.

    typedef boost::multi_array<float, 2> array2d;
    inline array2d read_m(const char *name)
    {
      typedef array2d::index index;
      ifstream data (name);
      index rows, cols;
      data >> rows >> cols;
      array_type m(boost::extents[rows][cols]);
      for(index i = 0; i != rows; ++i) 
        for(index j = 0; j != cols; ++j)
          data >> m[I][J];
      return m;
    }
    


  • #define READ_M(M, name) {ifstream data (name); data >> rows >> cols; float M [rows][cols]; for (int I = 0; I < rows; I++) { for (int J = 0; J < rows; J++) { data >> M [I] [J]; } } data.close(); }

    Das ist vollkommen unnötig und deshalb grauenvoll!

    Michael E. schrieb:

    Warum benutzt du ein Makro statt ner Funktion?

    Vollständig deiner Meinung!



  • nomakro schrieb:

    Meinst du wirklich, ein Funktionsaufruf macht bei hunderten von data.operator>>()-Aufrufen etwas aus?
    Du kannst es ja inline deklarieren, wenn du tatsächlich meinst, es sei entscheidend.

    typedef boost::multi_array<float, 2> array2d;
    inline array2d read_m(const char *name)
    {
      typedef array2d::index index;
      ifstream data (name);
      index rows, cols;
      data >> rows >> cols;
      array_type m(boost::extents[rows][cols]);
      for(index i = 0; i != rows; ++i) 
        for(index j = 0; j != cols; ++j)
          data >> m[I][J];
      return m;
    }
    

    Supi, das sieht doch gleich viel netter aus. Wusste bisher nicht von multiarrays 😕

    Viele Grüße,
    Kruemel



  • HighLigerBiMBam schrieb:

    #define READ_M(M, name) {ifstream data (name); data >> rows >> cols; float M [rows][cols]; for (int I = 0; I < rows; I++) { for (int J = 0; J < rows; J++) { data >> M [I] [J]; } } data.close(); }

    Das ist vollkommen unnötig und deshalb grauenvoll!

    Nein, nicht deshalb. Wenn es sich von einer Funktion nur dadurch unterscheiden würde, dass es als Makro definiert ist, ist das noch nicht gleich grauenvoll.

    Aber es benimmt sich 1. nicht wie eine Funktion und 2. führt es zu komischen Fehlermeldungen.

    READ_M(xp, "xp.txt"); // hä? was bedeutet das?
    ...
    int cols=10, y=3; // cols schon definiert. hä?
    

    Hingegen bei mir:

    array2d xp = read_m("xp.txt");
    int cols=10, y=3; // funktioniert
    xp[cols][y];
    

    Und noch dazu hat es überhaupt keinen overhead (allerdings ungetestet, kann alles Fehler enthalten, wie bei m[I][J]; anstelle von m[i][j]; ).

    HighLigerBiMBam schrieb:

    Vollständig deiner Meinung!

    Dann ist ja gut 😉


Log in to reply