我应该包括或在c++程序中?

时间:2023-01-13 10:54:41
  • What should I include in C++ programs, stdio.h or cstdio? and Why?
  • 我应该在c++程序stdio中包含什么?h或cstdio吗?,为什么?
  • Why two header files which provide the same functionality?
  • 为什么两个头文件提供相同的功能?
  • What does the standard say regarding this?
  • 关于这个,标准是怎么说的?
  • How should I go about including other such headers, Is there a base rule that I should follow?
  • 我应该如何包括其他这样的标题,是否有我应该遵循的基本规则?

2 个解决方案

#1


54  

Consider the following programs:

考虑以下程序:

Sample 1:

示例1:

#include<stdio.h>

int main()
{
    printf("Hello World");
    return 0;
}

Sample 2:

示例2:

#include<cstdio>

int main()
{
    printf("Hello World");
    return 0;
}

Both work as expected. So which usage is more appropriate? The answer is: Neither! Surprised? Read on.

像预期的那样工作。那么哪种用法更合适呢?答案是:没有!惊讶吗?继续读下去。

The C++ Standard library provides all standard C headers for compatibility reason, while C++ as a language also provides all the equivalent headers. As a convention,

由于兼容性的原因,c++标准库提供了所有标准的C标头,而c++作为一种语言也提供了所有等效的标头。作为一个惯例,

  • No C++ standard library headers(apart from ones include for C compatibility) have any file extensions, and
  • 没有c++标准库头(除了包含C兼容性)有任何文件扩展名,而且
  • All C++ equivalent of C headers begin with cxxxxx.
  • 所有的c++文件头都以cxxxxx开头。

The C++ Standard mentions this under Annex D (normative) Compatibility features:

C+标准在附件D(规范)兼容性特性中提到了这一点:

我应该包括或在c++程序中?

§2 mentions the important distinguishing point. This rule applied to the examples above means:

§2提到重要的区分点。适用于上述例子的这条规则意味着:

  • Including cstdio imports the symbol names in the std namespace and possibly in the Global namespace.
  • 包括cstdio导入std名称空间中的符号名称,也可能导入全局名称空间。
  • Including stdio.h imports the symbol names in the Global namespace and possibly in the std namespace.
  • 包括它的。h在全局命名空间中导入符号名称,也可能在std命名空间中导入。

Let us apply this rule to our sample codes and measure the pros and cons:

让我们将这条规则应用于我们的示例代码,并衡量利弊:

Sample 1: This brings all the symbols from stdio.h in the global namespace. Advantage is that you can use the symbols without any qualification since they are imported in the global namespace. Downside is that you end up polluting the global namespace with many symbol names that you will probably never use. This might lead to symbol name collision. In C++ always consider the global namespace as a minefield and avoid it as much as possible.

示例1:这是来自stdio的所有符号。在全局命名空间中的h。优点是您可以不加任何限定地使用符号,因为它们是在全局名称空间中导入的。缺点是,您最终会使用许多可能永远不会使用的符号名称来污染全局名称空间。这可能导致符号名称冲突。在c++中,总是把全局命名空间看作一个雷区,尽量避免它。

Sample 2: This is a very bad practice because there is no guarantee that the implementation will put the symbols in global namespace, the standard simply does not demand to do so. We are simply relying on the behavior of one particular compiler implementation. We cannot and should not assume that all compilers will do so. So strictly speaking the program is not standard approved and this usage is not portable across all implementations.

示例2:这是一个非常糟糕的实践,因为没有保证实现会将符号放在全局命名空间中,而标准只是不要求这样做。我们只是依赖于一个特定编译器实现的行为。我们不能也不应该假设所有的编译器都会这样做。因此严格地说,这个程序不是标准的批准,而且这种用法并不是在所有的实现中都可以移植。

So what is the correct usage?

The correct usage is to use cstdio and fully qualify the symbol names or else bring them in scope with using declarations. This guarantees all symbols we use are present in std namespace and we are not polluting the global namespace. Example of correct usage:

正确的用法是使用cstdio并且完全限定符号名称,或者使用声明将它们引入范围。这保证了我们使用的所有符号都出现在std名称空间中,并且不会污染全局名称空间。正确使用的例子:

Sample 3:

示例3:

#include<cstdio>

using std::printf;

int main()
{
    printf(“Hello World”);
    return 0;
}

Note that the directive using namespace std;, especially in a header, is not a good option and you should always use using declarations.

注意,使用名称空间std的指令,特别是在头中,不是一个好的选项,您应该始终使用声明。

Note that we consider stdio.h vs. cstdio here just a sample use case, in practice it applies to all most cxxxx and xxxx.h headers, except a few like <math.h> and <cmath>.

注意,我们考虑stdio。这里只是一个示例用例,实际上它适用于所有的cxxxx和xxxx。h页眉,除了一些像 和< cmath >。 。h>

#2


5  

Since this post is a bit old I wanted to share the following:

由于这篇文章有点过时,我想分享以下内容:


Looking at code:

Using X.h   // Compatible with C language standard
---------------
#include <X.h>

int main() {
    // Invoke X's corresponding function
    return 0;
}

Using X    // Not compatible with C language standard
--------------
#include <X>

int main() {
    // Invoke X's corresponding function
    return 0;
}

They both compile and execute ok!


Which one is better in C++?

Regarding C++11's and C++17's specification:

C.5.1 (section from C++17 document)
Modifications to headers [diff.mods.to.headers]

C.5.1(来自c++ 17文档的部分)对报头的修改

  1. For compatibility with the C standard library, the C++ standard library provides the C headers enumerated in D.5, but their use is deprecated in C++.

    为了与C标准库兼容,c++标准库提供了在D.5中枚举的C头,但是在c++中,它们的使用被弃用了。

  2. There are no C++ headers for the C headers <stdatomic.h>, <stdnoreturn.h>, and <threads.h>, nor are the C headers themselves part of C++.

    C报头 没有c++报头。h >,< stdnoreturn。h >,和 <线程。h> , C标头本身也不是c++的一部分。

  3. The C++ headers <ccomplex> (D.4.1) and <ctgmath> (D.4.4), as well as their corresponding C headers <complex.h> and <tgmath.h>, do not contain any of the content from the C standard library and instead merely include other headers from the C++ standard library.

    c++ header (D.4.1)和 (D.4.4),以及相应的C header 和< tgmath。h>,不包含任何来自C标准库的内容,只包含来自c++标准库的其他标题。 。h>


D.5 C standard library headers [depr.c.headers] 1. For compatibility with the C standard library, the C++ standard library provides the C headers shown in Table 141.

C标准库标题。头)1。为了与C标准库兼容,c++标准库提供了表141所示的C标头。

我应该包括或在c++程序中?

Both C++11 and C++17 standard specifications documents state the use of <X.h> remains for compatibility with the C standard, although their use is regarded as deprecated.

c++ 11和c++ 17标准规范文档都声明了 仍然与C标准兼容,尽管它们的使用被认为是不可取的。 的用法。h>


Regarding C++ 20 standard proposal

They are reviewing "undeprecating" the use of the C library headers in C++20. <X.h> appear highlighted in green. C++11 and C++17 deprecation, as of now, is stated as a "weak recommendation" and a "tweak" for keeping the "C standard library headers (c.headers)" is displayed below:

他们正在审查c++ 20中对C库头的使用。< X。h>以绿色突出显示。C++11和c++ 17的弃用,现在被认为是一个“弱推荐”和一个“调整”来保持“C标准库头(C .header)”显示在下面:

"The basic C library headers are an essential compatibility feature, and not going anywhere anytime soon." (from C++ 20 review document)

“基本的C库头是一个基本的兼容性特性,不会很快出现在任何地方。”(来自c++ 20评审文件)


D.5 C standard
library headers [depr.c.headers]

C标准库标头[depr.c.header]

Weak recommendation: In addition to the above, also remove the corresponding C headers from the C++ standard, much as we have no corresponding <stdatomic.h>, <stdnoreturn.h>, or <threads.h>, headers. As above, but with the following tweaks: 20.5.5.2.1 C standard library headers [c.headers]

弱推荐:除了以上之外,还从c++标准中删除相应的C标头,因为我们没有相应的 。h >,< stdnoreturn。h >或 <线程。h> ,页眉。如上所述,但是有以下调整:20.5.2.1 C标准库标题[C .header]

For compatibility with the C standard library, the C++ standard library provides the C headers shown in Table 141. Table 141 — C headers

为了与C标准库兼容,c++标准库提供了表141所示的C标头。表141 - C标题。

 <assert.h>  <inttypes.h>   <signal.h>      <stdio.h>   <wchar.h>
 <complex.h> <iso646.h>     <stdalign.h>    <stdlib.h>  <wctype.h>
 <ctype.h>   <limits.h>     <stdarg.h>      <string.h>  
 <errno.h>   <locale.h>     <stdbool.h>     <tgmath.h>
 <fenv.h>    <math.h>       <stddef.h>      <time.h>
 <float.h>   <setjmp.h>     <stdint.h>      <uchar.h>

The header <complex.h> behaves as if it simply includes the header . The header <tgmath.h> behaves as if it simply includes the headers <complex> and <cmath>.

标题 <复杂。h> 的行为就好像它只是包含了标题一样。标题< tgmath。h>的行为就好像它只是包含了header


Bjarne Stroustrup recommends maximising inter-operability between the C and C++ languages, by reducing imcompatibilities as much as possible. Others argue otherwise, as it complicates things.

Bjarne Stroustrup建议通过尽可能减少不兼容性来最大化C和c++语言之间的互操作性。其他人则持相反意见,因为这使事情变得复杂。

So, it seems <X.h> aren't going anywhere. Ultimately, you can use both. Personally, I would make the decision of which one I would use boil down to having your code backwards compatible with C code or not.

如此,< X。h >不会去任何地方。最终,您可以同时使用这两种方法。就我个人而言,我将决定我将使用哪一个,归结为您的代码是否向后兼容C代码。

#1


54  

Consider the following programs:

考虑以下程序:

Sample 1:

示例1:

#include<stdio.h>

int main()
{
    printf("Hello World");
    return 0;
}

Sample 2:

示例2:

#include<cstdio>

int main()
{
    printf("Hello World");
    return 0;
}

Both work as expected. So which usage is more appropriate? The answer is: Neither! Surprised? Read on.

像预期的那样工作。那么哪种用法更合适呢?答案是:没有!惊讶吗?继续读下去。

The C++ Standard library provides all standard C headers for compatibility reason, while C++ as a language also provides all the equivalent headers. As a convention,

由于兼容性的原因,c++标准库提供了所有标准的C标头,而c++作为一种语言也提供了所有等效的标头。作为一个惯例,

  • No C++ standard library headers(apart from ones include for C compatibility) have any file extensions, and
  • 没有c++标准库头(除了包含C兼容性)有任何文件扩展名,而且
  • All C++ equivalent of C headers begin with cxxxxx.
  • 所有的c++文件头都以cxxxxx开头。

The C++ Standard mentions this under Annex D (normative) Compatibility features:

C+标准在附件D(规范)兼容性特性中提到了这一点:

我应该包括或在c++程序中?

§2 mentions the important distinguishing point. This rule applied to the examples above means:

§2提到重要的区分点。适用于上述例子的这条规则意味着:

  • Including cstdio imports the symbol names in the std namespace and possibly in the Global namespace.
  • 包括cstdio导入std名称空间中的符号名称,也可能导入全局名称空间。
  • Including stdio.h imports the symbol names in the Global namespace and possibly in the std namespace.
  • 包括它的。h在全局命名空间中导入符号名称,也可能在std命名空间中导入。

Let us apply this rule to our sample codes and measure the pros and cons:

让我们将这条规则应用于我们的示例代码,并衡量利弊:

Sample 1: This brings all the symbols from stdio.h in the global namespace. Advantage is that you can use the symbols without any qualification since they are imported in the global namespace. Downside is that you end up polluting the global namespace with many symbol names that you will probably never use. This might lead to symbol name collision. In C++ always consider the global namespace as a minefield and avoid it as much as possible.

示例1:这是来自stdio的所有符号。在全局命名空间中的h。优点是您可以不加任何限定地使用符号,因为它们是在全局名称空间中导入的。缺点是,您最终会使用许多可能永远不会使用的符号名称来污染全局名称空间。这可能导致符号名称冲突。在c++中,总是把全局命名空间看作一个雷区,尽量避免它。

Sample 2: This is a very bad practice because there is no guarantee that the implementation will put the symbols in global namespace, the standard simply does not demand to do so. We are simply relying on the behavior of one particular compiler implementation. We cannot and should not assume that all compilers will do so. So strictly speaking the program is not standard approved and this usage is not portable across all implementations.

示例2:这是一个非常糟糕的实践,因为没有保证实现会将符号放在全局命名空间中,而标准只是不要求这样做。我们只是依赖于一个特定编译器实现的行为。我们不能也不应该假设所有的编译器都会这样做。因此严格地说,这个程序不是标准的批准,而且这种用法并不是在所有的实现中都可以移植。

So what is the correct usage?

The correct usage is to use cstdio and fully qualify the symbol names or else bring them in scope with using declarations. This guarantees all symbols we use are present in std namespace and we are not polluting the global namespace. Example of correct usage:

正确的用法是使用cstdio并且完全限定符号名称,或者使用声明将它们引入范围。这保证了我们使用的所有符号都出现在std名称空间中,并且不会污染全局名称空间。正确使用的例子:

Sample 3:

示例3:

#include<cstdio>

using std::printf;

int main()
{
    printf(“Hello World”);
    return 0;
}

Note that the directive using namespace std;, especially in a header, is not a good option and you should always use using declarations.

注意,使用名称空间std的指令,特别是在头中,不是一个好的选项,您应该始终使用声明。

Note that we consider stdio.h vs. cstdio here just a sample use case, in practice it applies to all most cxxxx and xxxx.h headers, except a few like <math.h> and <cmath>.

注意,我们考虑stdio。这里只是一个示例用例,实际上它适用于所有的cxxxx和xxxx。h页眉,除了一些像 和< cmath >。 。h>

#2


5  

Since this post is a bit old I wanted to share the following:

由于这篇文章有点过时,我想分享以下内容:


Looking at code:

Using X.h   // Compatible with C language standard
---------------
#include <X.h>

int main() {
    // Invoke X's corresponding function
    return 0;
}

Using X    // Not compatible with C language standard
--------------
#include <X>

int main() {
    // Invoke X's corresponding function
    return 0;
}

They both compile and execute ok!


Which one is better in C++?

Regarding C++11's and C++17's specification:

C.5.1 (section from C++17 document)
Modifications to headers [diff.mods.to.headers]

C.5.1(来自c++ 17文档的部分)对报头的修改

  1. For compatibility with the C standard library, the C++ standard library provides the C headers enumerated in D.5, but their use is deprecated in C++.

    为了与C标准库兼容,c++标准库提供了在D.5中枚举的C头,但是在c++中,它们的使用被弃用了。

  2. There are no C++ headers for the C headers <stdatomic.h>, <stdnoreturn.h>, and <threads.h>, nor are the C headers themselves part of C++.

    C报头 没有c++报头。h >,< stdnoreturn。h >,和 <线程。h> , C标头本身也不是c++的一部分。

  3. The C++ headers <ccomplex> (D.4.1) and <ctgmath> (D.4.4), as well as their corresponding C headers <complex.h> and <tgmath.h>, do not contain any of the content from the C standard library and instead merely include other headers from the C++ standard library.

    c++ header (D.4.1)和 (D.4.4),以及相应的C header 和< tgmath。h>,不包含任何来自C标准库的内容,只包含来自c++标准库的其他标题。 。h>


D.5 C standard library headers [depr.c.headers] 1. For compatibility with the C standard library, the C++ standard library provides the C headers shown in Table 141.

C标准库标题。头)1。为了与C标准库兼容,c++标准库提供了表141所示的C标头。

我应该包括或在c++程序中?

Both C++11 and C++17 standard specifications documents state the use of <X.h> remains for compatibility with the C standard, although their use is regarded as deprecated.

c++ 11和c++ 17标准规范文档都声明了 仍然与C标准兼容,尽管它们的使用被认为是不可取的。 的用法。h>


Regarding C++ 20 standard proposal

They are reviewing "undeprecating" the use of the C library headers in C++20. <X.h> appear highlighted in green. C++11 and C++17 deprecation, as of now, is stated as a "weak recommendation" and a "tweak" for keeping the "C standard library headers (c.headers)" is displayed below:

他们正在审查c++ 20中对C库头的使用。< X。h>以绿色突出显示。C++11和c++ 17的弃用,现在被认为是一个“弱推荐”和一个“调整”来保持“C标准库头(C .header)”显示在下面:

"The basic C library headers are an essential compatibility feature, and not going anywhere anytime soon." (from C++ 20 review document)

“基本的C库头是一个基本的兼容性特性,不会很快出现在任何地方。”(来自c++ 20评审文件)


D.5 C standard
library headers [depr.c.headers]

C标准库标头[depr.c.header]

Weak recommendation: In addition to the above, also remove the corresponding C headers from the C++ standard, much as we have no corresponding <stdatomic.h>, <stdnoreturn.h>, or <threads.h>, headers. As above, but with the following tweaks: 20.5.5.2.1 C standard library headers [c.headers]

弱推荐:除了以上之外,还从c++标准中删除相应的C标头,因为我们没有相应的 。h >,< stdnoreturn。h >或 <线程。h> ,页眉。如上所述,但是有以下调整:20.5.2.1 C标准库标题[C .header]

For compatibility with the C standard library, the C++ standard library provides the C headers shown in Table 141. Table 141 — C headers

为了与C标准库兼容,c++标准库提供了表141所示的C标头。表141 - C标题。

 <assert.h>  <inttypes.h>   <signal.h>      <stdio.h>   <wchar.h>
 <complex.h> <iso646.h>     <stdalign.h>    <stdlib.h>  <wctype.h>
 <ctype.h>   <limits.h>     <stdarg.h>      <string.h>  
 <errno.h>   <locale.h>     <stdbool.h>     <tgmath.h>
 <fenv.h>    <math.h>       <stddef.h>      <time.h>
 <float.h>   <setjmp.h>     <stdint.h>      <uchar.h>

The header <complex.h> behaves as if it simply includes the header . The header <tgmath.h> behaves as if it simply includes the headers <complex> and <cmath>.

标题 <复杂。h> 的行为就好像它只是包含了标题一样。标题< tgmath。h>的行为就好像它只是包含了header


Bjarne Stroustrup recommends maximising inter-operability between the C and C++ languages, by reducing imcompatibilities as much as possible. Others argue otherwise, as it complicates things.

Bjarne Stroustrup建议通过尽可能减少不兼容性来最大化C和c++语言之间的互操作性。其他人则持相反意见,因为这使事情变得复杂。

So, it seems <X.h> aren't going anywhere. Ultimately, you can use both. Personally, I would make the decision of which one I would use boil down to having your code backwards compatible with C code or not.

如此,< X。h >不会去任何地方。最终,您可以同时使用这两种方法。就我个人而言,我将决定我将使用哪一个,归结为您的代码是否向后兼容C代码。