来自 C 的指令 #include 和来自 C++ 的指令之间有什么区别吗?

Is there any difference between the directive #include from C and the one from C++?

这个问题在post中没有回答 #include <filename>#include “filename”有什么区别? 这是一个不同的问题。 我正在研究 C 和 C++ 之间的差异。我通过比较您可以用每种语言制作的最基本的程序来做到这一点:

在 C 中:

#include <stdio.h>
int main()
{
    printf("Hello World"); 
    return 0; 
}

在 C++ 中

#include <iostream>
int main()
{
  std::cout << "Hello World!!!" << std::endl;
  return 0;
}

我知道 headers 和编译过程。但我想知道 C 和 C++ 的 #include 指令之间是否有任何区别。例如,复制时的 header 内容可能以不同的方式复制。 我觉得这个问题很简单,你可以用"No"或者"yes, here are the differences: 1), 2)".

来回答

Like for example maybe the header content when is copied is copied in a different way.

#include 预处理器指令由 CPP 预处理器处理,即(大部分)与 C 和 C++ 编译相同。不同的 C 和 C++ 标准可能会引入 subtle differences, but none of these affects how the #include directive should be handled regarding how the file's content is replaced into the translation unit (besides how the header file names are expanded and matched, see @T.C.'s ).

CPP 仅进行文本替换,并将从包含的文件中看到的内容扩展到翻译单元中,无论是 C 还是 C++ 代码。

I think this question is very straightforward, you can answer it by saying "No" or "yes, here are the differences: 1), 2)".

不,#include 指令在文本替换方面没有区别。


嗯,从结果来看,C 编译器可能无法正确编译从 C++ 头文件展开的代码,有时反之亦然。

是的,至少有两点不同。在 C++ 中(WG21 N4567 [cpp.include]/5):

The implementation shall provide unique mappings for sequences consisting of one or more nondigits or digits (2.10) followed by a period (.) and a single nondigit. The first character shall not be a digit. The implementation may ignore distinctions of alphabetical case.

在 C 中(WG14 N1570 6.10.2/5,强调我的):

The implementation shall provide unique mappings for sequences consisting of one or more nondigits or digits (6.4.2.1) followed by a period (.) and a single nondigit. The first character shall not be a digit. The implementation may ignore distinctions of alphabetical case and restrict the mapping to eight significant characters before the period.

符合标准的 C 实现可以将“foobarbaz.h”和“foobarbat.h”映射到同一个源文件。符合标准的 C++ 实现不能。


此外,在 C (N1570 6.4.7) 中:

If the characters ', \, ", //, or /* occur in the sequence between the < and > delimiters, the behavior is undefined. Similarly, if the characters ', \, //, or /* occur in the sequence between the " delimiters, the behavior is undefined.

在 C++ 中 (N4567 [lex.header]/2):

The appearance of either of the characters ' or \ or of either of the character sequences /* or // in a q-char-sequence or an h-char-sequence is conditionally-supported with implementation-defined semantics, as is the appearance of the character " in an h-char-sequence.

"conditionally-supported with implementation-defined semantics" 表示

  • 如果实现不支持它,它必须发出诊断;
  • 如果实现确实支持它,则必须记录它对该构造的解释。

而"undefined behavior"意味着实现可以为所欲为。

在 C++ 中,通常会搜索更多目录。不过,这在技术上与 指令 没有区别。

例如,在我的系统上:

 % gcc -E -v -x c - <<< '' 2>&1 | sed -n '/cc1/,/End of search list/p'
 /usr/lib/gcc/x86_64-linux-gnu/5/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu - -mtune=generic -march=x86-64
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/5/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/5/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
% gcc -E -v -x c++ - <<< '' 2>&1 | sed -n '/cc1/,/End of search list/p'
 /usr/lib/gcc/x86_64-linux-gnu/5/cc1plus -E -quiet -v -imultiarch x86_64-linux-gnu -D_GNU_SOURCE - -mtune=generic -march=x86-64
ignoring duplicate directory "/usr/include/x86_64-linux-gnu/c++/5"
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/5/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/include/c++/5
 /usr/include/x86_64-linux-gnu/c++/5
 /usr/include/c++/5/backward
 /usr/lib/gcc/x86_64-linux-gnu/5/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/5/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.

此外,涉及#include的预处理器之间存在差异:

  • 命名运算符是 C++ 中内置的。在 C 中,您必须 #include <iso646.h>
  • 布尔关键字是 C++ 内置的。在 C 中,您必须 #include <stdbool.h>
  • 自 C++14 起,' 可用作数字分隔符。 (普遍认为这是个坏主意,但委员会不会接受其他任何东西)。