Frage

    

Diese Frage bereits eine Antwort hier:

         

Betrachten Sie diese (schrecklich, schrecklich, nicht gut, sehr schlecht) Code-Struktur:

#define foo(x) // commented out debugging code

// Misformatted to not obscure the point
if (a)
foo(a);
bar(a);

Ich habe zwei Compiler gesehen Preprozessoren unterschiedliche Ergebnisse auf diesem Code zu generieren:

if (a)
bar(a);

und

if (a)
;
bar(a);

Offensichtlich ist dies eine schlechte Sache für einen tragbaren Codebasis.

Meine Frage: Was ist der Prä-Prozessor mit, dies tun sollte? Elide Kommentare zuerst, oder erweitern Makros zuerst?

War es hilfreich?

Lösung

Leider ist die ursprüngliche ANSI-C-Spezifikation schließt ausdrücklich alle Preprocessor Funktionen in Abschnitt 4 ( „Diese Spezifikation beschreibt nur die C-Sprache. Dabei spielt es keine Bestimmung entweder für die Bibliothek oder den Präprozessor.“).

Die C99 Spezifikation diese explicity Griffe , though. Die Kommentare werden mit einem einzigen Raum in der „Übersetzung Phase“ ersetzt, die vor der Präprozessordirektive Parsen geschieht. (Abschnitt 6.10 für weitere Details).

VC ++ und die GNU C Compiler beide folgen sie diesem Paradigma - andere Compiler möglicherweise nicht kompatibel sein, wenn sie sind älter, aber wenn es C99-konform ist, sollten Sie sicher sein.

Andere Tipps

Wie in beschrieben diese Kopie-n-klebte decription der Übersetzungsphasen in dem C99-Standard, das Entfernen von Kommentaren (sie von einem einzelnen Leerzeichen ersetzt werden) tritt in Übersetzung Phase 3, während der Vorverarbeitung Richtlinien behandelt werden und Makros werden in Phase 4 erweitert.

In der C90-Standard (die ich nur in Papierform haben, so dass keine Kopie-n-Paste) sind diese zwei Phasen erfolgen in der gleichen Reihenfolge, obwohl die Beschreibung der Übersetzung Phasen in einigen Details von der C99-Standard ist etwas anders -. die Tatsache, dass die Kommentare von einem einzelnen Leerzeichen vor Vorverarbeitung Richtlinien behandelt werden, werden entfernt und ersetzt und Makros erweitert ist nicht anders

Auch hier ist der C ++ Standard hat diese 2 Phasen in der gleichen Reihenfolge auftreten.

Was, wie die '// Kommentare behandelt werden sollen, sagt der C99-Standard dieses (6.4.9 / 2):

  

Mit Ausnahme innerhalb einer Zeichenkonstante, einem Stringliteral oder einem Kommentar, die Zeichen //   einführen einen Kommentar, der alle Mehrbytezeichen bis zu, aber nicht einschließlich enthält, die   nächste new-line Zeichen.

Und die C ++ Standard sagt (2.7):

  

Die Zeichen // einen Kommentar starten, die mit dem nächsten Newline beendet   Charakter.

So Ihr erstes Beispiel ist eindeutig ein Fehler seitens des Übersetzers - die ‚;‘ Zeichen nach dem foo(a) sollten beibehalten werden, wenn die foo() Makro erweitert wird - die Kommentarzeichen nicht als Teil des ‚Inhalts‘ von the foo() sein sollten Makro.

Aber da du mit einem Buggy Übersetzer konfrontiert sind, könnten Sie die Makrodefinition ändern möchten:

#define foo(x) /* junk */

, um den Fehler zu umgehen.

Allerdings (und ich Abdriften Thema hier ...), da die Leitung Spleißen (Schrägstriche kurz vor einer neuen Zeile) auftritt, bevor Kommentare verarbeitet werden, können Sie so etwas wie dieses bisschen bösen Code ausführen in:

#define evil( x) printf( "hello "); // hi there, \
                 printf( "%s\n", x); // you!



int main( int argc, char** argv)
{
    evil( "bastard");

    return 0;
}

Was könnte überraschen, wer es geschrieben hat.

Oder noch besser, versuchen Sie die folgenden, von jemandem geschrieben (! Schon gar nicht ich), die mag Box-Stil Kommentare:

int main( int argc, char** argv)
{
                            //----------------/
    printf( "hello ");      // Hey, what the??/
    printf( "%s\n", "you"); // heck??         /
                            //----------------/
    return 0;
}

Je nachdem, ob der Compiler standardmäßig auf die Verarbeitung trigraphs oder nicht (Compiler sollen, aber da trigraphs Überraschung fast jeder, der über sie läuft, sie einige Compiler entscheiden Standardeinstellung), Sie können oder nicht bekommen das gewünschte Verhalten deaktivieren -. Was auch immer Verhalten, das ist natürlich

Nach MSDN werden Kommentare ersetzt mit einem einzigen Raum in der tokenization Phase, das geschieht, bevor die Vorlaufphase, wo Makros erweitert werden.

Nie // Kommentare in Ihren Makros setzen. Wenn Sie Kommentare setzen müssen, verwenden Sie / * * /. Darüber hinaus haben Sie einen Fehler in Ihrem Makro:

#define foo(x) do { } while(0) /* junk */

Auf diese Weise foo ist immer sicher zu bedienen. Zum Beispiel:

if (some condition)
    foo(x);

wird nie einen Compiler-Fehler, unabhängig davon, ob werfen oder nicht foo zu einem gewissen Ausdruck definiert sind.

#ifdef _TEST_
#define _cerr cerr
#else
#define _cerr / ## / cerr
#endif
  • wird auf einigen Compiler arbeiten (VC ++). Wenn _TEST_ nicht definiert ist,

    _cerr ...

    wird durch die Kommentarzeile ersetzt werden

    // cerr ...

Ich scheine, dass die Einhaltung erfordert drei Schritte zu erinnern:

  1. Streifen
  2. erweitern Makros
  3. Streifen wieder

Der Grund dafür hat mit dem Compiler zu tun Lage, .i zu akzeptieren Dateien direkt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top