Einrücken #definiert

Lesezeit: 7 Minuten

Benutzeravatar von Rocketmagnet
Raketenmagnet

ich weiß das #defines usw. werden normalerweise nie eingerückt. Wieso den?

Ich arbeite gerade an einem Code, der eine schreckliche Mischung aus enthält #defines, #ifdefs, #elses, #endifs usw. All dies wird oft mit normalem C-Code vermischt. Das Nichteinrücken der #defines macht sie schwer lesbar. Und die Mischung aus eingerücktem Code mit nicht eingerücktem #defines ist ein Albtraum.

Warum sind #defines typischerweise nicht eingerückt? Gibt es einen Grund, warum man nicht einrücken würde (z. B. wie dieser Code unten)?

#ifdef SDCC
    #if DEBUGGING == 1
        #if defined (pic18f2480)
            #define FLASH_MEMORY_END 0x3DC0
        #elif defined (pic18f2580)
            #define FLASH_MEMORY_END 0x7DC0
        #else
            #error "Can't set  up flash memory end!"
        #endif
    #else
        #if defined (pic18f2480)
            #define FLASH_MEMORY_END 0x4000
        #elif defined (pic18f2580)
            #define FLASH_MEMORY_END 0x8000
        #else
            #error "Can't set  up flash memory end!"
        #endif
    #endif
#else
    #if DEBUGGING == 1
        #define FLASH_MEMORY_END 0x7DC0
    #else
        #define FLASH_MEMORY_END 0x8000
    #endif
#endif

Pre-ANSI C-Präprozessor erlaubte kein Leerzeichen zwischen dem Beginn einer Zeile und dem Zeichen “#”. das führende „#“ musste immer in der ersten Spalte stehen.

Pre-ANSI-C-Compiler gibt es heutzutage nicht mehr. Verwenden Sie den Stil (Leerzeichen vor “#” oder Leerzeichen zwischen “#” und dem Bezeichner), den Sie bevorzugen.

http://www.delorie.com/gnu/docs/gcc/cpp_48.html

Benutzeravatar von Patrick Schlüter
Patrick Schlüter

Wie einige bereits gesagt haben, erforderten einige Pre-ANSI-Compiler, dass das # das erste Zeichen in der Zeile ist, aber sie verlangten nicht, dass die Direktive de preprocessor daran angehängt wird, also wurde die Einrückung auf diese Weise vorgenommen.

#ifdef SDCC
#  if DEBUGGING == 1
#    if defined (pic18f2480)
#      define FLASH_MEMORY_END 0x3DC0
#    elif defined (pic18f2580)
#      define FLASH_MEMORY_END 0x7DC0
#    else
#      error "Can't set  up flash memory end!"
#    endif
#  else
#    if defined (pic18f2480)
#      define FLASH_MEMORY_END 0x4000
#    elif defined (pic18f2580)
#      define FLASH_MEMORY_END 0x8000
#    else
#      error "Can't set  up flash memory end!"
#    endif
#  endif
#else
#  if DEBUGGING == 1
#    define FLASH_MEMORY_END 0x7DC0
#  else
#    define FLASH_MEMORY_END 0x8000
#  endif
#endif

Ich habe diesen Stil oft in alten Unix-Headern gesehen, aber ich hasse ihn, da die Syntaxfärbung bei solchem ​​Code oft fehlschlägt. Ich verwende eine sehr gut sichtbare Farbe für Präprozessoranweisungen, damit sie hervorstechen (sie befinden sich auf einer Metaebene und sollten daher nicht Teil des normalen Codeflusses sein). Sie können sogar sehen, dass SO die Sequenz nicht sinnvoll einfärbt.

In Bezug auf das Parsen von Präprozessordirektiven war der C99-Standard (und der C89-Standard davor) klar über die Abfolge der vom Compiler logisch ausgeführten Operationen. Insbesondere glaube ich, dass dieser Code bedeutet:

/* */ # /* */ include /* */ <stdio.h> /* */

ist äquivalent zu:

#include <stdio.h>

GCC 3.4.4 mit ‘-std=c89 -pedantic’ akzeptiert wohl oder übel die mit Kommentaren beladene Zeile jedenfalls. Ich befürworte das nicht als Stil – nicht für eine Sekunde (es ist grässlich). Ich denke nur, dass es möglich ist.

ISO/IEC 9899:1999 Abschnitt 5.1.1.2 Übersetzungsphasen sagt:

  1. [Character mapping, including trigraphs]

  2. [Line splicing – removing backslash newline]

  3. Die Quelldatei wird in Vorverarbeitungstoken und Sequenzen von Leerzeichen (einschließlich Kommentaren) zerlegt. Eine Quelldatei darf nicht mit einem teilweisen Vorverarbeitungstoken oder einem teilweisen Kommentar enden. Jeder Kommentar wird durch ein Leerzeichen ersetzt. Zeilenumbrüche bleiben erhalten. Ob jede nicht leere Folge von Leerzeichen außer New-Line beibehalten oder durch ein Leerzeichen ersetzt wird, ist implementierungsdefiniert.

  4. Vorverarbeitungsanweisungen werden ausgeführt, Makroaufrufe werden erweitert, […]

Abschnitt 6.10 Vorverarbeitungsanweisungen sagt:

Eine Vorverarbeitungsanweisung besteht aus einer Folge von Vorverarbeitungstoken, die mit einem #-Vorverarbeitungstoken beginnt, das (zu Beginn der Übersetzungsphase 4) entweder das erste Zeichen in der Quelldatei ist (optional nach Leerzeichen, die keine Zeilenumbruchzeichen enthalten) oder das folgt auf Leerzeichen, die mindestens ein Zeilenumbruchzeichen enthalten, und wird durch das nächste Zeilenumbruchzeichen beendet.

Einziger möglicher Streitpunkt ist der Klammerausdruck ‘(at the start of translation phase 4)’, was bedeuten könnte, dass die Kommentare vor der Raute fehlen müssen, da sie sonst bis zum Ende von Phase 4 nicht durch Leerzeichen ersetzt werden.

Wie andere angemerkt haben, verhielten sich die Vorstandard-C-Präprozessoren in vielerlei Hinsicht nicht einheitlich, und Leerzeichen vor und in Präprozessor-Direktiven waren einer der Bereiche, in denen verschiedene Compiler unterschiedliche Dinge taten, einschließlich der Nichterkennung von Präprozessor-Direktiven mit Leerzeichen davor .

Es ist bemerkenswert, dass Backslash-Newline-Entfernung erfolgt, bevor Kommentare analysiert werden. Folglich sollten Sie nicht enden // Kommentare mit einem Backslash.

Ich weiß nicht, warum es nicht häufiger vorkommt. Es gibt sicherlich Zeiten, in denen ich gerne Präprozessordirektiven einrücke.

Eine Sache, die mir immer wieder im Weg steht (und mich manchmal davon überzeugt, es nicht weiter zu versuchen), ist, dass viele oder die meisten Editoren/IDEs die Direktive bei der geringsten Provokation in Spalte 1 werfen. Was höllisch nervt.

Heutzutage glaube ich, dass dies hauptsächlich eine Wahl des Stils ist. ich denken An einem Punkt in der fernen Vergangenheit unterstützten nicht alle Compiler den Begriff des Einrückens von Präprozessordefinitionen. Ich habe etwas recherchiert und konnte diese Behauptung nicht belegen. Aber auf jeden Fall scheinen alle modernen Compiler die Idee des Einrückens von Präprozessormakros zu unterstützen. Ich habe jedoch keine Kopie des C- oder C++-Standards, daher weiß ich nicht, ob dies ein Standardverhalten ist oder nicht.

Ob es guter Stil ist oder nicht. Mir persönlich gefällt die Idee, sie alle auf der linken Seite zu halten. Es gibt Ihnen einen einheitlichen Ort, an dem Sie nach ihnen suchen können. Ja, es kann nervig werden, wenn es sehr verschachtelte Makros gibt. Aber wenn Sie sie einrücken, erhalten Sie am Ende noch seltsamer aussehenden Code.

#if COND1
void foo() {
  #if COND2
  int i;
    #if COND3
  i = someFunction()
  cout << i << eol;
    #endif
  #endif
}
#endif

  • Der Grund, warum dieser Code seltsam aussieht, liegt darin, dass Sie zwei “Streams” von Einrückungen erstellt haben. Ich würde Zeile 4 um eine weitere Ebene einrücken, und ich würde die Zeilen 6 und 7 um zwei weitere Ebenen einrücken.

    – Kevin Laity

    15. Oktober 2009 um 20:58 Uhr

  • Völlig einverstanden. Manchmal setze ich sogar Klammern, damit die #ifs genauso aussehen wie die ifs.

    – bash05

    10. März 2010 um 5:21 Uhr

  • Ich bemühe mich sehr, meinen Code so anzuordnen, dass er es hat nein #ifdef Zeilen in den Teilen, in denen ich tatsächlichen Code habe. Wenn ich bedingtes Zeug benötige, füge ich es stattdessen entweder in ausgelagerte Funktionen oder ausgelagerte Makros ein; es ist viel klarer, wie ich finde (na ja, zumindest ist es für mich). Im Idealfall befinden sich all diese ausgeklammerten Teile in anderen Dateien (Header oder bedingt kompilierte Quelldateien; die übliche „Bedingung“ ist, für welche Plattform der Code erstellt wird).

    – Donal Fellows

    3. Juli 2010 um 9:09 Uhr

  • Ich würde die Zeilen 4 um eine Ebene und die Zeilen 6 und 7 um zwei Ebenen einrücken.

    – Raketenmagnet

    14. September 2010 um 20:53 Uhr

Benutzeravatar von Daniel Fortunov
Daniel Fortunov

Für das Beispiel, das Sie gegeben haben, kann es angebracht sein, Einrückungen zu verwenden, um es klarer zu machen, da Sie eine so komplexe Struktur verschachtelter Anweisungen haben.

Persönlich denke ich, dass es nützlich ist, sie die meiste Zeit nicht eingerückt zu lassen, da diese Direktiven getrennt vom Rest Ihres Codes funktionieren. Direktiven wie #ifdef werden vom Präprozessor verarbeitet, bevor der Compiler Ihren Code überhaupt sieht, sodass ein Codeblock nach einer #ifdef-Direktive möglicherweise nicht einmal vorhanden ist zusammengestellt.

Es ist wichtiger, Direktiven visuell vom Rest Ihres Codes zu trennen, wenn sie mit Code durchsetzt sind (anstelle eines dedizierten Blocks von Direktiven, wie in dem Beispiel, das Sie geben).

  • Der Grund, warum dieser Code seltsam aussieht, liegt darin, dass Sie zwei “Streams” von Einrückungen erstellt haben. Ich würde Zeile 4 um eine weitere Ebene einrücken, und ich würde die Zeilen 6 und 7 um zwei weitere Ebenen einrücken.

    – Kevin Laity

    15. Oktober 2009 um 20:58 Uhr

  • Völlig einverstanden. Manchmal setze ich sogar Klammern, damit die #ifs genauso aussehen wie die ifs.

    – bash05

    10. März 2010 um 5:21 Uhr

  • Ich bemühe mich sehr, meinen Code so anzuordnen, dass er es hat nein #ifdef Zeilen in den Teilen, in denen ich tatsächlichen Code habe. Wenn ich bedingtes Zeug benötige, füge ich es stattdessen entweder in ausgelagerte Funktionen oder ausgelagerte Makros ein; es ist viel klarer, wie ich finde (na ja, zumindest ist es für mich). Im Idealfall befinden sich all diese ausgeklammerten Teile in anderen Dateien (Header oder bedingt kompilierte Quelldateien; die übliche „Bedingung“ ist, für welche Plattform der Code erstellt wird).

    – Donal Fellows

    3. Juli 2010 um 9:09 Uhr

  • Ich würde die Zeilen 4 um eine Ebene und die Zeilen 6 und 7 um zwei Ebenen einrücken.

    – Raketenmagnet

    14. September 2010 um 20:53 Uhr

In fast allen derzeit verfügbaren C/CPP-Compilern ist es nicht eingeschränkt. Es ist Sache des Benutzers, zu entscheiden, wie Sie Code ausrichten möchten. Also viel Spaß beim Codieren.

  • Anständige Antwort. Könnten Sie es verbessern, indem Sie einige spezifische Styleguide-Referenzen hinzufügen?

    – EtherDragon

    21. November 2019 um 16:48 Uhr

1422300cookie-checkEinrücken #definiert

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

Privacy policy