it-swarm.com.de

Ist der Backslash in C- und C++ # include-Direktiven akzeptabel?

Es gibt zwei gebräuchliche Pfadtrennzeichen: den Unix-Schrägstrich und den DOS-Backslash. Ruhe in Frieden, Classic Mac Doppelpunkt. Wenn sie in einer # include-Direktive verwendet werden, sind sie nach den Regeln der Standards C++ 11, C++ 03 und C99 gleich?

38
Potatoswatter

C99 sagt (§ 6.4.7/3):

Wenn die Zeichen ', \, ", // oder/* in der Reihenfolge zwischen den Trennzeichen <und> vorkommen, ist das Verhalten undefiniert. Ebenso, wenn die Zeichen', \, // oder/* in der Folge vorkommen zwischen den Trennzeichen ist das Verhalten undefiniert.

(Fußnote: Sequenzen von Zeichen, die Escape-Sequenzen ähneln, führen daher zu undefiniertem Verhalten.)

C++ 03 sagt (§2.8/2):

Wenn eines der Zeichen 'oder\oder eine der Zeichenfolgen/* oder // in einer q-Zeichenfolge oder einer h-Zeichenfolge oder das Zeichen "in einer h-Zeichenfolge erscheint, erscheint das Verhalten ist undefiniert.

(Fußnote: Sequenzen von Zeichen, die Escape-Sequenzen ähneln, führen daher zu undefiniertem Verhalten.)

C++ 11 sagt (§2.9/2):

Das Auftreten eines der Zeichen 'oder\oder einer der Zeichenfolgen/* oder // in einer q-char-Sequenz oder einer h-char-Sequenz wird mit implementierungsdefinierter Semantik ebenso wie das Auftreten von unterstützt das Zeichen "in einer h-Zeichenfolge.

(Fußnote: Eine Folge von Zeichen, die einer Escape-Sequenz ähnelt, kann daher zu einem Fehler führen, als das der Escape-Sequenz entsprechende Zeichen interpretiert werden oder je nach Implementierung eine völlig andere Bedeutung haben.)

Obwohl jeder Compiler sich dafür entscheidet, einen Backslash in einem #include-Pfad zu unterstützen, ist es unwahrscheinlich, dass ein Compiler-Anbieter den Schrägstrich nicht unterstützt, und Backslashes führen wahrscheinlich dazu, dass einige Implementierungen durch das Erstellen von Escape-Codes ausgelöst werden. (Edit: anscheinend hat MSVC zuvor einen Backslash benötigt. Vielleicht waren andere auf DOS abgeleiteten Plattformen ähnlich. Hmmm ... was soll ich sagen.)

C++ 11 scheint die Regeln zu lockern, aber "bedingt unterstützt" ist nicht sinnvoll besser als "führt zu undefiniertem Verhalten". Die Änderung spiegelt mehr die Existenz bestimmter populärer Compiler wider als die Beschreibung eines tragbaren Standards.

Natürlich sagt nichts in einer dieser Standards, dass es so etwas wie Pfade gibt. Es gibt gibt Dateisysteme ohne Pfade! Viele Bibliotheken gehen jedoch von Pfadnamen aus, einschließlich POSIX und Boost. Daher ist es sinnvoll, auf tragbare Weise auf Dateien in Unterverzeichnissen zu verweisen.

47
Potatoswatter

Der Schrägstrich ist der richtige Weg. Der Pre-Compiler wird auf jeder Plattform alles tun, um zur richtigen Datei zu gelangen.

7
trojanfoe

Es hängt davon ab, was Sie mit "akzeptabel" meinen.

Es gibt zwei Sinne, in denen Schrägstriche akzeptabel sind und Backslashes nicht.

Wenn Sie C99, C++ 03 oder C1x schreiben, sind Backslashes nicht definiert, während Schrägstriche zulässig sind. In diesem Sinne sind Backslashes nicht zulässig.

Dies ist jedoch für die meisten Menschen irrelevant. Wenn Sie C++ 1x schreiben, wo Backslashes bedingt unterstützt werden und die Plattform, für die Sie programmieren, diese unterstützt, sind sie akzeptabel. Und wenn Sie einen "erweiterten Dialekt" von C99/C++ 03/C1x schreiben, der Backslashes definiert, gilt das gleiche. Und was noch wichtiger ist, diese Vorstellung von "akzeptabel" ist in den meisten Fällen sowieso ziemlich bedeutungslos. Keiner der C/C++ - Standards definiert, was Schrägstriche bedeuten (oder was Backslashes bedeutet, wenn sie bedingt unterstützt werden). Header-Namen werden den Quelldateien in einer implementierungsdefinierten Weise zugeordnet (Punkt). Wenn Sie über eine Hierarchie von Dateien verfügen und Sie fragen, ob Sie Backslashes oder Schrägstriche verwenden möchten, um sie portabel in # include-Direktiven zu referenzieren, lautet die Antwort: Keine ist portabel. Wenn Sie wirklich portablen Code schreiben möchten, können Sie keine Hierarchien von Header-Dateien verwenden. In der Tat ist es am besten, dass Sie alles in eine einzige Quelldatei schreiben und nichts anderes als Standard-Header einschließen.

In der realen Welt wollen die Menschen jedoch oft "tragbar genug" und nicht "streng tragbar". Der POSIX-Standard legt fest, was Schrägstriche bedeutet, und sogar über POSIX hinaus behandeln die meisten modernen Plattformen - einschließlich Win32 (und Win64), Cross-Compiler für eingebettete und mobile Plattformen wie Symbian usw. - Schrägstriche zumindest bis zu POSIX C/C++ - # include-Direktiven. Jede Plattform, die dies nicht tut, hat wahrscheinlich keine Möglichkeit, Ihren Quelltextbaum zu erhalten, Ihr Makefile/etc zu verarbeiten und so weiter, so dass die Anweisungen #include die geringste Ihrer Sorgen sein werden. Wenn Sie sich darum kümmern, dann sind Schrägstriche akzeptabel, aber Backslashes nicht.

5
abarnert

Blackslash ist undefiniertes Verhalten und selbst bei einem Schrägstrich muss man vorsichtig sein. Der C99-Standard lautet:

Wenn die Zeichen ', \, ", // oder /* ..____.] In der Reihenfolge zwischen den Trennzeichen < Und> vorkommen, ist das Verhalten Undefined Zeichen ', \, // oder/* kommen in der Reihenfolge zwischen den "Trennzeichen" vor, das Verhalten ist nicht definiert.

5
Jens Gustedt

Verwenden Sie immer Schrägstriche - sie funktionieren auf mehreren Plattformen. Backslash verursacht technisch ein undefiniertes Verhalten in C++ 03 (2,8/2 im Standard).

1
Alan Stokes

Der Standard sagt für #include, dass es:

durchsucht eine Folge implementierungsdefinierter Stellen nach einem Header, der eindeutig durch die angegebene Sequenz zwischen den Trennzeichen identifiziert wird, und bewirkt, dass diese Direktive durch den gesamten Inhalt des Headers ersetzt wird . Wie die Bereiche angegeben oder der Header Identifiziert wird, ist durch die Implementierung definiert.

Beachten Sie den letzten Satz.

0