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

时间:2011-04-26 12:17:27

标签: c++ c include c-preprocessor header-files

常用的路径分隔符有两种:Unix正斜杠和DOS反斜杠。 安静地休息,Classic Mac冒号。 如果在#include指令中使用,它们在C ++ 11,C ++ 03和C99的规则下是否相同标准?

6 个答案:

答案 0 :(得分: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,因此想要一种可移植的方式来引用子目录中的文件是合理的。

答案 1 :(得分:7)

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

答案 2 :(得分:5)

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

  

如果字符',\,“,//或/ *   以<之间的顺序发生。   和>分隔符,行为是   未定义。同样,如果   字符',\,//或/ *出现在   “分隔符之间的顺序,   行为未定义。

答案 3 :(得分: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指令将是你最不担心的。如果那是你关心的,那么斜线是可以接受的,但反斜杠不是。

答案 4 :(得分:1)

始终使用正斜杠 - 它们适用于更多平台。反斜杠在技术上导致C ++ 03中的未定义行为(标准中为2.8 / 2)。

答案 5 :(得分:0)

标准说#include它:

  

搜索一系列实现定义的地点   由指定序列唯一标识的标头   分隔符,并导致该指令的替换   标题的全部内容。如何指定地点或标题   确定是实施定义的。

请注意最后一句。