我应该在C ++程序中包含<xxxx.h>还是<cxxxx>吗?

  • 我应该在C ++程序stdio.hcstdio中包含什么? 为什么?
  • 为什么两个提供相同功能的头文件?
  • 标准对此有何说法?
  • 我应该如何包括其他此类标头?是否有应遵循的基本规则?
Alok Save asked 2020-02-08T07:28:15Z
2个解决方案
60 votes

请考虑以下程序:

范例1:

#include<stdio.h>

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

范例2:

#include<cstdio>

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

两者都按预期工作。 那么哪种用法更合适?答案是:都不是! 惊讶吗 继续阅读。

出于兼容性原因,C ++标准库提供了所有标准C头,而C ++作为一种语言还提供了所有等效的头。 按照惯例

  • 没有C ++标准库标头(除了为了C兼容性而包含的标头)没有任何文件扩展名,并且
  • 与C头相同的所有C ++都以cxxxxx开头。

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

Standard Citation

§2提到了重要的区别点。 适用于以上示例的此规则表示:

  • 包括cstdio在内的符号名称将导入std名称空间中,也可能在Global名称空间中。
  • 包括stdio.h在内的全局名称空间和可能的std名称空间中都将导入符号名称。

让我们将此规则应用于示例代码并衡量其优缺点:

范例1:这会将来自stdio.h的所有符号带入全局名称空间。 优点是,由于符号是在全局名称空间中导入的,因此可以无限制地使用它们。 不利的一面是,您最终用许多您可能永远不会使用的符号名称来污染全局名称空间。 这可能导致符号名称冲突。 在C ++中,始终将全局名称空间视为雷区,并尽可能避免使用它。

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

那么正确的用法是什么?

正确的用法是使用<math.h>并完全限定符号名称,否则将它们包含在<math.h>声明中。 这保证了我们使用的所有符号都存在于<cmath>命名空间中,并且我们不会污染全局命名空间。 正确用法示例:

范例3:

#include<cstdio>

using std::printf;

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

请注意,指令<math.h>(尤其是在标头中)不是一个好的选择,您应始终使用<math.h>声明。

请注意,我们将<math.h><cmath>进行比较,这里仅是一个示例用例,实际上,它适用于所有大多数cxxxxxxxx.h标头,除了少数几个如<math.h><cmath>

Alok Save answered 2020-02-08T07:29:47Z
5 votes

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


看代码:

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;
}

它们都可以编译并执行!


在C ++中哪个更好?

关于C ++ 11和C ++ 17的规范:

C.5.1(C ++ 17文档中的部分)
标题的修改[diff.mods.to.headers]

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

  2. C标头<X.h><complex><tgmath.h>没有C ++标头,C标头本身也没有   C ++的一部分。

  3. C ++标头<X.h>(D.4.1)和<complex>(D.4.4)以及它们相应的C标头<tgmath.h><complex>   包含C标准库中的任何内容,而是   仅包含C ++标准库中的其他标头。


D.5   C标准库头文件[depr.c.headers]   1.为了与C标准库兼容,C ++标准库提供了表141中所示的C标头。

enter image description here

C ++ 11和C ++ 17标准规范文档均声明仍保留使用<X.h>来与C标准兼容,尽管它们的使用被视为已弃用。


关于C ++ 20标准提案

他们正在审查“过分赞成” C ++ 20中C库头文件的使用。 <X.h>以绿色突出显示。 到目前为止,C ++ 11和C ++ 17的弃用被声明为“弱推荐”,并且在下面显示了用于保留“ C标准库标头(c.headers)”的“调整”:

“基本的C库标头是必不可少的兼容性功能,并且很快就不会出现在任何地方。” (来自C ++ 20审查文档)


D.5 C标准
库标题[depr.c.headers]

弱推荐:除上述内容外,还删除   C ++标准中相应的C标头,因为我们没有   相应的标题<X.h><complex><tgmath.h>。   如上所述,但有以下调整:   20.5.5.2.1 C标准库头文件[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>

标头<X.h>   行为就像它只是包含标题<complex>。   标头<tgmath.h>的行为就好像它仅包含标头<complex><cmath>


Bjarne Stroustrup建议最大程度地实现以下两者之间的互操作性   C和C ++语言,通过最大程度地减少不兼容性   可能。 其他人则相反,因为它使事情复杂化。

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

Santiago Varela answered 2020-02-08T07:31:43Z
translate from https://stackoverflow.com:/questions/13889467/should-i-include-xxxx-h-or-cxxxx-in-c-programs