为什么两者都“std::printf"?和“printf"使用 <cstdio> 时编译而不是 <stdio.h>在 C++ 中?

2022-01-14 00:00:00 namespaces c++ header-files

据我所知,cxyz 形式的标题与 xyz.h 相同,唯一的区别是 cxyz 将所有xyz.h 的内容在命名空间 std 下.为什么下面的程序都在 GCC 4.9 和 clang 6.0 上编译?

To my knowledge, headers of the form cxyz are identical to xyz.h with the only difference being that cxyz places all of the contents of xyz.h under the namespace std. Why is it that the following programs both compile on GCC 4.9 and clang 6.0?

#include <cstdio>

int main() {
    printf("Testing...");
    return 0;
}

和第二个程序:

#include <cstdio>

int main() {
    std::printf("Testing...");
    return 0;
}

FILE 结构也是如此:

The same goes for the FILE struct:

FILE* test = fopen("test.txt", "w");

std::FILE* test = std::fopen("test.txt", "w");

两者都有效.

直到现在,我一直认为最好使用 cstdiocstring 等,而不是使用它们的非命名空间对应物.但是,以上两个程序中哪个是更好的做法?

Up until now, I always thought that it was better to use cstdio, cstring, etc, rather than their non-namespaced counterparts. However, which of the following two programs above are better practice?

其他 C 函数也是如此,例如 memset(来自 cstring)、scanf(也来自 cstdio)等.

The same goes for other C functions such as memset (from cstring), scanf (also from cstdio), etc.

(我知道有些人会问我为什么在 C++ 程序中使用 C IO;这里的问题不是专门针对 C IO,而是在没有具体指定 std:: 在调用命名空间的 C 函数之前.)

(I know some people will ask why I am using C IO in a C++ program; the issue here is not specifically C IO, but whether or not this code should compile without specifically specifying std:: before calling a namespaced C function.)

推荐答案

该标准允许编译器也将名称注入全局命名空间.

The standard permits the compiler to also inject the names into the global namespace.

这样做的一个原因是它允许 <cstdio> 的实现为:

One reason for this is that it permits the implementation of <cstdio> to be:

#include <stdio.h>

namespace std
{
    using ::printf;
    using ::fopen;
    // etc.
}

因此编译器/库供应商不必编写和维护这么多代码.

so the compiler/library vendor does not have to write and maintain so much code.

在您自己的代码中,始终使用 std::using namespace std; 等,以便您的代码可移植到不将名称注入全局的编译器命名空间.

In your own code, always use std:: or using namespace std; etc. so that your code is portable to compilers which do not inject the names into global namespace.

相关文章