6

这个代码标准符合吗?

#include <stdio.h>
#include <cstdio>

int main() {
    FILE *f1 = 0;
    std::FILE *f2 = f1;
}

解释:标准说[标题]:

[...] 每个标题的内容cname应与相应标题的内容相同name.h[...] 如同被包含一样。然而,在 C++ 标准库中,声明 [...] 在 namespace 的命名空间范围 (3.3.6) 内std未指定这些名称是否首先在全局命名空间范围内声明,然后通过显式使用声明(7.3.3)注入命名空间。std

因此,如果它们不是通过显式使用声明注入的,它们可能是不同的类型吗?我不认为“好像通过包含”短语是决定性的,因为文本的另一半显然与此要求相矛盾,要求名称在std命名空间内。

4

3 回答 3

3

是的,这是符合标准的:在、in 中FILE*声明,并且由于您引用的段落,两者是相同的。stdio.hstd::FILE*cstdio

(唯一未指定的是,如果您包含,您是否在全局命名空间中<cstdio>也有相同的内容。)FILE*


更新:我相信这些类型实际上是相同的,并且每种类型只声明一次,然后通过using声明注入另一个命名空间。唯一未指定的是哪个先出现。相应的相反标准引用是 D.5(2):

每个 C 标头(每个都具有 name.h 形式的名称)的行为就好像每个由相应 cname 标头放置在标准库命名空间中的名称都放置在全局命名空间范围内一样。未指定这些名称是否首先在命名空间 std 的命名空间范围 (3.3.6) 内声明或定义,然后通过显式使用声明 (7.3.3) 注入全局命名空间范围。

基本上,这意味着两种实现是可能的:

“C先来”:

// foo.h

struct Gizmo { /* ... */ };

// cfoo

#include "foo.h"
namespace std { using ::Gizmo; }


“具有 C 兼容性的 C++:

// cfoo

namespace std 
{
    struct Gizmo { /* ... */ };
}

// foo.h

#include <cfoo>
using std::Gizmo;
于 2012-05-05T21:32:14.763 回答
2

我不相信那段说它们必须相同。它只是对原始 (C++98) 段落的修订,该段落说:

每个 C 头文件,每个都有一个name.h形式的名称,其行为就像每个由相应cname头文件放置在标准库名称空间中的名称也被放置在名称空间的名称空间范围内,std并且后跟显式使用声明(7.3.3)

这是难以理解的,因为它与大多数系统上现有的真实C 头文件相冲突。因此,在 C++11 中,文本已更改为您引用的文本。它允许以相反的方式实现它,就像他们在实践中一直所做的那样 - 使用现有系统提供的 C 头文件并将名称导入到 namespace std

但是,还有一段说无论实现方式如何,标题中的名称都必须表示相同的含义:

T对于标准 C 库中的每种类型,类型::Tstd::T保留给实现,并且在定义::T时应与std::T. ([extern.types], 17.6.4.3.4)

于 2012-05-06T09:50:17.757 回答
1

是的,它们可以是不同的类型。使用 C++ 类型;C 头文件只是为了兼容性。

考虑是否如上述答案的评论所暗示的那样,C++ 标头被实现为namespace std { #include "stdio.h" }; 那么::FILEstd::FILE将代表不同的类型。

于 2012-05-05T21:24:47.310 回答