DITTY Geschrieben 12. Juli 2009 Geschrieben 12. Juli 2009 Sers COM, Ich habe eine Frage bzgl. der Präprozessor-Direktive #define: Syntax: #define bezeichner ersatzliste #define bezeichner(bezeichner_liste) ersatzliste Link: C/C++ - Direktive #define Ich weis, dass der erstere Fall dazu gedacht ist, sowas, wie Konstanten zuschaffen (zumindest bei C) bzw. eigene Schlüsselwärter zu definieren. 1.) Wurden auch so die Schlüsselwörter int, float, bool, etc. definiert und zur Verfügung gestellt? Wenn ja, wie schaut da die Definition aus? Ich meine, das deklarieren eines int, float, bool etc. schaut ja wie folgt aus: typ Bezeichner [= Zuweisung] Wie muss man #define anwenden, um ähnliches zu realisieren, sprich um z.B. eigene Datentypen anzubieten, sodass man später im Programmcode Variablen des eigenen Datentyps anlegen kann: eigener_datentyp Bezeichner [= Zuweisung] 2.) Kann man mittels #define auch ähnliche Konstrukte, wie for, while, do-while, switch, if, else, etc. realisieren? Wenn ja, wie? 3.) #define bezeichner(bezeichner_liste) ersatzliste Wie muss man das verstehen. Für was steht die Bezeichner-Liste und wie verwendet man später eigene mittels #define erzeugte Signalwörter, welche auf diese Art und Weise erzeugt wurden? #################################### Ich danke vielmals im Vorraus! Gruß DITTY :):) Zitieren
Guybrush Threepwood Geschrieben 12. Juli 2009 Geschrieben 12. Juli 2009 define schafft keine Schlüsselwörter sondern ist nur eine einfache Textersetzung. Das heißt wenn du zum Beispiel #define MAX 5 schreibst dann in deinem Quellcode vor dem Kompilieren einfach überall MAX durch 5 ersetzt und danach wird es erst kompiliert. Zitieren
Crush Geschrieben 12. Juli 2009 Geschrieben 12. Juli 2009 Ergänzend übernehme ich mal Folgendes direkt aus einem anderen Forum: #define SQUARE(a) a*a int x = 5; int y = SQUARE (x+2); /* berechnet wird: y = x + (2*x) + 2 */ Brjane Stroustroup äussert sich in seinem berühmten Buch "Die C++ Programmiersprache" wie folgt: "Fast jedes Makro demonstriert eine Schwäche in der Programmiersprache, im Programm oder beim Programmierer. Da Makros den Programmtext ändern, bevor der Compiler ihn richtig liest, sind Makros außerdem ein großes Problem für viele Programmierwerkzeuge. Wenn man also Makros benutzt, muß man schlechtere Dienste von Werkzeugen wie Debuggern, Crossreferenz-Werkzeugen und Profilern erwarten." Zitieren
Klotzkopp Geschrieben 12. Juli 2009 Geschrieben 12. Juli 2009 Wurden auch so die Schlüsselwörter int, float, bool, etc. definiert und zur Verfügung gestellt?Nein. Kann auch gar nicht sein, weil Define-Direktiven Neues nur auf bereits Bestehendes zurückführen können. Irgendetwas muss also schon vorher da sein. Wie muss man #define anwenden, um ähnliches zu realisieren, sprich um z.B. eigene Datentypen anzubieten, sodass man später im Programmcode Variablen des eigenen Datentyps anlegen kann: eigener_datentyp Bezeichner [= Zuweisung]Dafür brauchst du keine Define-Direktive, da tut's eine Struktur- oder Klassendefinition oder ein Typedef. Kann man mittels #define auch ähnliche Konstrukte, wie for, while, do-while, switch, if, else, etc. realisieren? Wenn ja, wie?Ja, kann man, aber glaub mir, das willst du nicht. Für was steht die Bezeichner-ListePräprozessormakros können wie Funktionen eine Parameterliste haben, wobei die Parameter natürlich nur Namen und keine Typen haben. Im Rumpf des Makros kann dann auf diese Parameter Bezug genommen werden. Siehe das a in Crushs Beispiel. und wie verwendet man später eigene mittels #define erzeugte Signalwörter, welche auf diese Art und Weise erzeugt wurden?Am Besten gar nicht. Das geht zwar mit Makros, aber so etwas sollte man sich nicht antun. Makros sind Dumm. Sie kennen keinen Scope, sie erlauben keine Typprüfung, man kann sie nicht überladen, sie erschweren das Debugging. Fehler in Makros sind zum Teil sehr schwer zu finden. Von seltene benötigten Ausnahmen abgesehen, gibt es nur einen einzigen Einsatzzweck von Makros in C++: Include-Guards für Headerdateien, also das #ifndef/#define/#endif-Gerüst, das Mehrfacheinbindungen desselben Headers verhindert. Von allen anderen Anwendungen von Makros sollten gerade Anfänger meiner Meinung nach die Finger lassen. Zitieren
Schlitzauge Geschrieben 22. Februar 2013 Geschrieben 22. Februar 2013 Sers, Hab da ein neues Projekt am laufen und bzgl. #defines eine Frage. define schafft keine Schlüsselwörter sondern ist nur eine einfache Textersetzung. Ok, bereits reservierte Wörter zu redefinieren scheint wirklich nicht zu gehen. Was ich aber gerne machen würde ist, Zeichen und Zeichenketten zu definieren. Also etwa #define ^ * oder #define := = oder auch ganze Zeichenketten: #define "DO i = 1, 4711 {...} ENDDO" "for(i=1;i<=4711;++i){{...}}" Es heißt ja, dass der Präprozessor bzw. die Präprozessordirektive #define nichts weiteres macht, als entsprechende Definitionen vor dem eigentlichen Compilieren im Quelltext zu ersetzen / übersetzen. Ich suche eine Möglichkeit, sich hier nicht nur auf klassische Symbolwörter (also Wörter nur aus Buchstaben und Zahlen) zu beschränken. Geht das irgendwie, den #define-Befehl oder andere Mittel von C/C++ zum übersetzen von Text zu verwenden? Auf Codegeneratoren und / oder Übersetzer-Tools möchte ich nicht zurückgreifen, sondern das Ganze allein mit C/C++-Mitteln realisieren, sodass meine Quelltexte dann auch entsprechend mit beliebigen C/C++-Compilern übersetzt werden können. Und, gibt es nicht doch eine Möglichkeit bereits reservierte Wörter, wie "int" zu redefinieren?, etwa: struct|class INT { public: int var; }; #define int INT() Damit könnte ich aus skalaren Typen, wie int z.B. Struktur- bzw. Klassenobjekte machen, ähnlich wie in C#. Grüße Schlitzauge Zitieren
Klotzkopp Geschrieben 22. Februar 2013 Geschrieben 22. Februar 2013 Was ich aber gerne machen würde ist, Zeichen und Zeichenketten zu definieren.Geht nicht. Das Präprozessorsymbol, das #define erzeugt, muss den Regeln für Bezeichner folgen. Auf Codegeneratoren und / oder Übersetzer-Tools möchte ich nicht zurückgreifen, sondern das Ganze allein mit C/C++-Mitteln realisieren, sodass meine Quelltexte dann auch entsprechend mit beliebigen C/C++-Compilern übersetzt werden können.Das stellt sich spätestens dann als schlechte Idee heraus, wenn der Compiler über Fehler meckert, die wegen der Makro-Orgien im ursrpünglichen Code gar nicht zu finden sind. Und, gibt es nicht doch eine Möglichkeit bereits reservierte Wörter, wie "int" zu redefinieren?Wer hat denn gesagt, dass das nicht geht? #define int INT() Damit könnte ich aus skalaren Typen, wie int z.B. Struktur- bzw. Klassenobjekte machen, ähnlich wie in C#.Nö, könntest du nicht. Ich kann dir nur deutlichst raten: Lass das. Dafür sind Makros nicht gedacht. Zitieren
Schlitzauge Geschrieben 22. Februar 2013 Geschrieben 22. Februar 2013 Es ist vielmehr ein Machbarkeitsexperiment, ob da je was ernsthaftes drauß wird, wohl eher nicht. Mich interessieren einfach mal die Grenzen und ob man nicht doch die eine oder andere Grenze sprengen bzw. erweitern könnte. Falls wer Ideen dazu hat, bitte... Wer hat denn gesagt, dass das nicht geht? Ja? Hab ich ja nicht behauptet. Wie würde sowas aussehen? Ich kann mit #define und typedefs "neue" Typen festlegen oder bestehende "umbenennen", aber dann eben nur andersgeschrieben. Ich wollte gerne sowas wie eine Typenerweiterung von int und Co. praktizieren. Also dass man weiterhin entsprechend der C/C++-Syntax eine int-Variable anlegen kann, z.B.: int var1 = 0; var1 dann aber eben nicht nur eine int-Variable ist, sondern ein struct / class mit gleichen Typ-Namen int. Wenn das irgendwie gehen sollte, wäre ich sehr daran interessiert, thx. Zitieren
Klotzkopp Geschrieben 22. Februar 2013 Geschrieben 22. Februar 2013 Ja? Hab ich ja nicht behauptet. Doch, hast du: Ok, bereits reservierte Wörter zu redefinieren scheint wirklich nicht zu gehen. Wie würde sowas aussehen?#define int wasauchimmer Also dass man weiterhin entsprechend der C/C++-Syntax eine int-Variable anlegen kann, z.B.: int var1 = 0; var1 dann aber eben nicht nur eine int-Variable ist, sondern ein struct / class mit gleichen Typ-Namen int. Das Problem dabei ist, dass sich dein neuer int nicht genauso verhält wie ein richtiger int. Und sobald dein Makro auf Code losgelassen wird, der sich auf eben dieses Verhalten von int verlässt, knallt es. Zitieren
Schlitzauge Geschrieben 22. Februar 2013 Geschrieben 22. Februar 2013 (bearbeitet) #define int wasauchimmer #include <iostream> using namespace std; int main(int argc, char* argv[]) { #define int float int test1 = 5.458; cout << test1 << endl; #define int int int test2 = 5.458; cout << test2; getchar(); return 0; } Dein Hinweis war top. Ig werd bekloppt, dass funktioniert ja wirklich. Komisch. Ich hatte es irgendwie die ganze Zeit in Erinnerung, dass das nicht geht bzw. der Compiler seinen Dienst quitiert, weil bereits reservierte Schlüsselwörter manipuliert werden. Vlt. liegts auch einfach nur daran, dass man sowas eigentlich nicht macht und ich das mal so gelernt habe. Ok, wieder was dazugelernt. EDIT: Ok, mit typedefs kann man sowas aber leider nicht machen. Das Problem dabei ist, dass sich dein neuer int nicht genauso verhält wie ein richtiger int. Und sobald dein Makro auf Code losgelassen wird, der sich auf eben dieses Verhalten von int verlässt, knallt es. Richtig, deshalb geht mein Gedanke auch in Richtung Bereichskapselung a´la OpenMP, dann sollte auch nichts mehr knallen. Na perfekt, fehlt nur noch die Möglichkeit Sonderzeichen zu redefinieren, halt sowas: #define := = #define ^ * Hier getestet quitiert der Compiler aber den Vorgang, da kein Bezeichner: [C++ Fehler] Unit1.cpp(5): E2153 Für die Define-Anweisung ist ein Bezeichner erforderlich. Gibts da nicht Möglichkeiten??? Bearbeitet 22. Februar 2013 von Schlitzauge Zitieren
Klotzkopp Geschrieben 22. Februar 2013 Geschrieben 22. Februar 2013 Komisch. Ich hatte es irgendwie die ganze Zeit in Erinnerung, dass das nicht geht bzw. der Compiler seinen Dienst quitiert, weil bereits reservierte Schlüsselwörter manipuliert werden.Wie sollte er? Der Compiler bekommt davon überhaupt nichts mit. Richtig, deshalb geht mein Gedanke auch in Richtung Bereichskapselung a´la OpenMP, dann sollte auch nichts mehr knallen.Dann kannst du aber nicht den normalen C++-Präprozessor nehmen. Der macht, wie gesagt, nur eine stumpfe Textersetzung, und ist für solche Vorhaben das falsche Werkzeug. Gibts da nicht Möglichkeiten???Wie bereits gesagt, das Präprozessorsymbol muss den Anforderungen eines Bezeichners genügen. := ist kein Bezeichner, und ^ auch nicht. Zitieren
Schlitzauge Geschrieben 22. Februar 2013 Geschrieben 22. Februar 2013 Wie sollte er? Der Compiler bekommt davon überhaupt nichts mit. Hab ich gerade in meiner Selbsterkenntnis selber bemerkt: Ig werd bekloppt, dass funktioniert ja wirklich. Das habe ich mir schon fast gedacht. Schade, wäre ein ziemlich mächtiger Präprozessor gewesen und würde mir viel Arbeit bei meinem Vorhaben ersparen. Da werde ich um externe Tools wohl nicht drumherum kommen... Falls doch noch wer Ideen oder vermeintliche "Unlösungen" dazu finden sollte, bitte... Ich hab jetzt zumindets einige Ansätze, die ich weiterverfolgen werde... Thx, Grüße Schlitzauge Zitieren
Klotzkopp Geschrieben 22. Februar 2013 Geschrieben 22. Februar 2013 Schade, wäre ein ziemlich mächtiger Präprozessor gewesen und würde mir viel Arbeit bei meinem Vorhaben ersparen. Nein, der C++-Präprozessor ist wirklich eher einfach. Falls doch noch wer Ideen oder vermeintliche "Unlösungen" dazu finden sollte, bitte...Bastel dir doch deinen eigenen Präprozessor, der tut, was du willst. Zitieren
Schlitzauge Geschrieben 22. Februar 2013 Geschrieben 22. Februar 2013 Nein, der C++-Präprozessor ist wirklich eher einfach. Naja, zumindest mächtiger als jeden anderen den ich kenne (Pascal, C#, Fortran, etc.). Bastel dir doch deinen eigenen Präprozessor, der tut, was du willst. Ganz im Ernst? Geht das, also so, dass man das direkt dann in C/C++ nutzen kann (also mit jedem C/C++-kompatiblen Compiler)??? Da würde ich gerne mal ein Beispiel sehen. Wüsste jetzt nicht, wonach ich da googlen soll... Zitieren
Klotzkopp Geschrieben 22. Februar 2013 Geschrieben 22. Februar 2013 Naja, zumindest mächtiger als jeden anderen den ich kenne (Pascal, C#, Fortran, etc.). Du wirfst hier die Makro-Fähigkeiten einer Sprache mit dem Werkzeug, das diese umsetzt, durcheinander. C# hat keinen Präprozessor. Es braucht auch keinen. Geht das, also so, dass man das direkt dann in C/C++ nutzen kann (also mit jedem C/C++-kompatiblen Compiler)???Ein Präprozessor ist einfach nur ein Programm, das Daten einliest, verarbeitet und wieder ausgibt. Da steckt doch keine Magie dahinter. Schau dir doch mal an, wie Qt das mit seinem moc macht. Das ist auch nur ein Programm, das Qt-Code nimmt und daraus ganz normales C++ macht. Das wird dann eben einfach in die Toolchain integriert. Zitieren
KuhTee Geschrieben 23. Februar 2013 Geschrieben 23. Februar 2013 Ergänzend übernehme ich mal Folgendes direkt aus einem anderen Forum: Das Beispiel ist aber eher schlecht, wenn man Mängel im Preprocessor zeigen will. Wenn der Programmierer zu dumm ist, Klammern richtig zu setzen, dann kann ja schliesslich der Preprocessor nix dafür. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.