Ist es falsch, Präprozessordirektiven in ein funktionsähnliches Makro einzufügen?

Lesezeit: 4 Minuten

Benutzer-Avatar
sop

Ich weiß, dass meine Frage dieser oder dieser ähnlich ist, aber ich finde, dass sie nicht wirklich dieselbe ist, und mehr noch, die zweite hat keine akzeptierte Antwort, ich habe mich entschieden zu fragen, ob es richtig ist, Präprozessordirektiven hinzuzufügen, wann ein funktionsähnliches Makro aufgerufen wird?

In meinem Fall habe ich ein funktionsähnliches Makro:

#define FUNC_MACRO(a, b)  // do something with the variables

und irgendwo im Code nenne ich es mit einem bestimmten Unterschied, wenn ein anderes Makro definiert ist:

// ...
FUNC_MACRO(aVal
#ifdef ANOTHER_MACRO
                + offset
#endif // ANOTHER_MACRO
           , bVal);
// ...

Ich habe es auf meinem Computer (Linux, mit gcc 4.8) getestet und es hat gut funktioniert (mit und ohne Präprozessordirektiven und mit und ohne ANOTHER_MACRO definiert), aber ist es sicher, dies zu tun?

Ich habe den Absatz 16.3/9 aus der Antwort auf die erste ähnliche Frage gelesen, aber gilt er auch für meinen Fall?

  • “Aber ist es sicher, das zu tun?” Definieren sicher bitte.

    – πάντα ῥεῖ

    16. September 2016 um 15:02 Uhr

  • Ist das C oder C++? In C++ gibt es bessere Alternativen.

    – Bathseba

    16. September 2016 um 15:03 Uhr

  • Generell sollten Makros nach Möglichkeit vermieden werden. Makros, die den Code verschleiern, sollten unbedingt vermieden werden.

    – Eugen Sch.

    16. September 2016 um 15:03 Uhr

  • Das erwähnte Makro und die ifdefs fühlen sich sehr falsch an. Sie sollten versuchen, einen anderen Weg in der Logik zu finden, bevor Sie versuchen, ein solches Makro aufzurufen

    – bgeschka

    16. September 2016 um 15:08 Uhr

  • Dies ist zu weit gefasst, es sollte eine Frage pro Programmiersprache geben und die Antwort ist nicht unbedingt für jede Sprache gleich.

    – Wertigkeit

    16. September 2016 um 21:59 Uhr

Benutzer-Avatar
R.. GitHub HÖREN SIE AUF, ICE ZU HELFEN

Die C-Sprache belässt dies als undefiniertes Verhalten in 6.10.3 Makroersetzung, ¶11:

Wenn in der Liste der Argumente Sequenzen von Vorverarbeitungstoken vorhanden sind, die ansonsten als Vorverarbeitungsanweisungen fungieren würden, ist das Verhalten nicht definiert.

Es ist also in der Tat falsch, es zu tun.

GCC und vielleicht andere populäre Kompilierungen verstehen es nicht, was wahrscheinlich der Grund dafür ist, dass viele Benutzer der Sprache sich dessen nicht bewusst sind. Ich bin darauf gestoßen, als ein Teil meines Codes auf PCC nicht kompiliert werden konnte (und den Fehler in meinem Code umgehend behoben hat).

Update: PJTraill hat in den Kommentaren nach einem Fall gefragt, in dem es „irreführend oder bedeutungslos“ wäre, Präprozessordirektiven in einer Makroerweiterung zu haben. Hier ist eine offensichtliche:

    foo(a, b,
#ifdef BAR
        c);
#else
        d);
#endif

Ich bin mir nicht sicher, ob es für die Sprache plausibel gewesen wäre, dies anzugeben ausgewogen Präprozessorbedingungen innerhalb der Makroerweiterung sind in Ordnung, aber ich denke, Sie würden auch dort auf Probleme mit Mehrdeutigkeiten in der Reihenfolge stoßen, in der sie verarbeitet werden sollten.

  • Das ist gut zu wissen, aber angesichts der Tatsache, wie oft Microsoft Methoden “anpassen” muss, um über ASCII und Unicode oder “normal” und “sicher” usw. zu funktionieren, würde ich hoffen, dass ihre Compiler dies tatsächlich unterstützen. IMHO, der springende Punkt bei einem Makro ist, dass Sie nicht wissen müssen, dass es ein Makro ist.

    – Mark Hurd

    21. September 2016 um 5:21 Uhr

  • Das scheint schlüssig, aber auf den ersten Blick scheint es eine intuitiv vernünftige Interpretation des Codes zu geben – können Sie den Sprachstandard mit einem Fall begründen, in dem er irreführend oder bedeutungslos wäre?

    – PJTrail

    21. September 2016 um 11:55 Uhr

  • Offensichtlich können Sie explizit ein Szenario einrichten, in dem die #if soll “innerhalb” eines Makros ausgewertet werden, aber ich würde davon ausgehen, dass das verständlichste Verhalten immer die Auswertung von Any wäre #if-ähnliche Vorverarbeitungstoken vor der Makroerweiterung.

    – Mark Hurd

    9. Oktober 2016 um 3:21 Uhr

Benutzer-Avatar
Tobi

Gehen Sie stattdessen wie folgt vor?

#ifdef ANOTHER_MACRO
FUNC_MACRO(aVal + offset, bVal);
#else
FUNC_MACRO(aVal, bVal);
#endif

BEARBEITEN: Umgang mit Bedenken, die durch einen Kommentar geäußert wurden; Ich weiß nicht, ob die Methode des OP ist speziell falsch (ich denke, andere Antworten decken das ab). Prägnanz und Klarheit sind jedoch zwei Aspekte, die beim Codieren mit C als ziemlich wichtig angesehen werden.

Daher würde ich es viel vorziehen, bessere Wege zu finden, um das zu erreichen, was das OP zu versuchen scheint, indem ich die Situation, wie ich sie oben angeboten habe, leicht überdenke. Ich denke, das OP hat vielleicht ein trivialisiertes Beispiel verwendet, aber ich finde normalerweise bei den meisten C-Situationen, dass es bessere Möglichkeiten gibt, das zu erreichen, was benötigt wird, wenn etwas übermäßig komplex wird oder versucht, etwas zu tun, was die Sprache nicht zulassen sollte .

  • Das ist eine Lösung, keine Antwort. Eine Sache, die sicher funktioniert, um eine andere zu vermeiden, die vielleicht nicht funktioniert, aber wir wissen es wirklich nicht. Er will es aber genau wissen.

    – Peregring-lk

    16. September 2016 um 19:06 Uhr

  • @Peregring-lk Du liegst falsch. How to Answer begrüßt ausdrücklich Antworten, die alternative Lösungen aufzeigen: „Die Antwort kann lauten ‚tu das nicht‘, aber sie sollte auch ‚versuchen Sie das stattdessen‘ beinhalten.“ Das ist nicht die Beste beantworten, da eine großartige Antwort auch erklären würde, warum sie zusammen mit der Alternative schlecht ist, aber es ist eine legitime Antwort auf die Frage.

    – jpmc26

    16. September 2016 um 20:16 Uhr


1375020cookie-checkIst es falsch, Präprozessordirektiven in ein funktionsähnliches Makro einzufügen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy