C和C++ #include指令中的反斜杠是否可以接受?

Pot*_*ter 39 c c++ include header-files c-preprocessor

常用的路径分隔符有两种:Unix正斜杠和DOS反斜杠.安息吧,经典的Mac冒号.如果在#include指令中使用,它们是否符合C++ 11,C++ 03和C99标准的规则?

Pot*_*ter 47

C99说(§6.4.7/ 3):

如果字符',\,",//或/*出现在<和>分隔符之间的序列中,则行为未定义.同样,如果字符',\,//或/*出现在序列中在"分隔符之间,行为是不确定的.

(脚注:因此,类似转义序列的字符序列会导致未定义的行为.)

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

如果字符'或'中的任何一个,或者字符序列/*或//中的任何一个出现在q-char-序列或h-char-序列中,或者字符"出现在h-char序列中,则行为未定义.

(脚注:因此,类似转义序列的字符序列会导致未定义的行为.)

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

在q-char序列或h-char序列中,字符'或\或任一字符序列/*或//中的任一个的出现都是通过实现定义的语义有条件地支持的,因为它的外观是字符"在一个h-char序列中.

(脚注:因此,类似于转义序列的字符序列可能会导致错误,被解释为与转义序列对应的字符,或者具有完全不同的含义,具体取决于实现.)

因此,尽管任何编译器都可能选择在#include路径中支持反斜杠,但是任何编译器供应商都不太可能不支持正斜杠,并且反斜杠可能会因为形成转义码而使某些实现失效.(编辑:显然MSVC以前需要反斜杠.也许在DOS衍生平台上的其他人类似.嗯......我能说什么.)

C++ 11 似乎放松了规则,但"有条件支持"并没有比"导致未定义的行为"更有意义.这种变化更多地反映了某些流行编译器的存在,而不是描述便携式标准.

当然,这些标准中的任何一个都没有说道路有这样的东西.那里文件系统没有路径!但是,许多库都假设路径名,包括POSIX和Boost,因此想要一种可移植的方式来引用子目录中的文件是合理的.


tro*_*foe 7

正斜杠是正确的方法; 预编译器将在每个平台上执行任何操作以获取正确的文件.

  • @Xeo这不依赖于MSVC,它是Windows本身:现代Windowses接受正斜杠作为路径分隔符; Windows 98没有(AFAIR). (3认同)
  • 标准中绝对_nothing_表示正斜杠是强制性的,也不是"预编译器"(我假设你在这里谈论编译器的预处理器阶段)将神奇地把它变成任何必要的东西.几乎整个事情都是实现定义的. (2认同)

Jen*_*edt 6

Blackslash是未定义的行为,即使有斜线,你也要小心.C99标准规定:

如果字符',\,",//或/*出现在<和>分隔符之间的序列中,则行为未定义.同样,如果字符',\,//或/*出现在序列中在"分隔符之间,行为是不确定的.


aba*_*ert 5

这取决于你所说的"可接受".

有两种感觉,斜线是可以接受的,而反斜杠则不是.

如果您正在编写C99,C++ 03或C1x,则反斜杠是未定义的,而斜杠是合法的,因此从这个意义上讲,反斜杠是不可接受的.

但这对大多数人来说无关紧要.如果您正在编写C++ 1x,有条件地支持反斜杠,并且您编写的平台支持它们,那么它们是可以接受的.如果你正在写一个C99/C++ 03/C1x的"扩展方言",它定义了反斜杠,同样的交易.而且,更重要的是,无论如何,这种"可接受"的概念在大多数情况下都是毫无意义的.没有一个C/C++标准定义什么斜杠的意思(或什么反斜杠意味着它们是有条件支持的).标头名称以实现定义的方式映射到源文件.如果你有一个文件层次结构,并且你正在询问是否使用反斜杠或斜杠在#include指令中可移植地引用它们,答案是:它们都不是可移植的.如果你想编写真正可移植的代码,你就不能使用头文件的层次结构 - 事实上,可以说,最好的办法是将所有东西都写在一个源文件中,而不是#include除标准头之外的任何东西.

然而,在现实世界中,人们经常想要"便携式",而不是"严格便携".POSIX标准规定了什么斜杠,甚至超出POSIX,大多数现代平台 - 包括Win32(和Win64),嵌入式和移动平台的交叉编译器,如Symbian等,至少可以处理POSIX方式,至少C/C++ #include指令.任何没有的平台,可能都没有任何方法让你将源代码树放到它上面,处理你的makefile /等等,所以#include指令将是你最不担心的.如果这是你关心的,那么斜线是可以接受的,但反斜杠不是.