C标准库中的符号是否保留在C++中?
这是对不同问题的跟进。
最初的问题还有其他问题,但我必须意识到主要问题(根据 CLang)是重新定义time为不同的符号,而只使用了很好的C++ 包含。
所以这是一个精简版:
#include<iostream>
using std::cout;
using std::endl;
class time
{
public:
int h, min, sec;
};
const int full = 60;
void canonify(time& pre) // Error here (line 14)
{
pre.min += pre.sec / full;
pre.h += pre.min / full;
pre.sec %= full;
pre.min %= full;
}
int main()
{
time a; // and here (line 23)
a.h = 3;
a.min = 128;
a.sec = 70;
canonify(a);
cout << a.h << ":" << a.min << ":" << a.sec << endl;
}
当然,用time不同的符号替换或使用struct time就足以解决问题。换种说法,我的问题不是如何让代码运行,而是我们是否必须将 C 库中的符号视为C++ 中的保留标记。Clang 11(在 MSVC19 上)扼流圈:
1>ess.cpp(14,15): error : must use 'class' tag to refer to type 'time' in this scope
1>...ucrttime.h(518,42): message : class 'time' is hidden by a non-type declaration of 'time' here
1>ess.cpp(23,5): error : must use 'class' tag to refer to type 'time' in this scope
1>...ucrttime.h(518,42): message : class 'time' is hidden by a non-type declaration of 'time' here
所以问题是:当 C++ 标准没有明确包含在编译单元中时,C++ 标准在哪里禁止自由使用 C 标准库中的符号?
有趣的是,相同的代码(一旦翻译...)在 C 中运行良好:
#include <stdio.h>
//
typedef struct
{
int h, min, sec;
}time;
//
const int full = 60;
//
void canonify(time* pre)
{
pre->min += pre->sec / full;
pre->h += pre->min / full;
pre->sec %= full;
pre->min %= full;
}
int main()
{
time a;
a.h = 3;
a.min = 128;
a.sec = 70;
canonify(&a);
printf("%d:%d:%dn", a.h, a.min, a.sec);
return 0;
}
回答
[外部名称]
3使用外部链接声明的 C 标准库中的每个名称都保留给实现用作具有外部“C”链接的名称,在命名空间 std 和全局命名空间中。
请注意,本段保留了名称本身。所以time在全局命名空间中使用别名违反了这个约定。
- 解决方案是将您自己的“时间”包装在您自己的“命名空间”中。
- @Eljay - 需要注意的是,您可能不会为此使用 C 语言链接。
- @Eljay 这是每个声明都应该做的事情(除了那个命名空间和`main`之类的东西。我想跨语言接口。)
- 谢谢,我找不到那个参考。但是C标准库中的符号数量是*laaaarge*,我希望很多程序员都不知道它们......
回答
C++ 标准在哪里禁止自由使用 C 标准库中的符号
最新草稿:
[外部名称]
使用外部链接声明的 C 标准库中的每个名称都保留给实现用作具有外部“C”链接的名称,在命名空间 std 和全局命名空间中。
使用外部链接声明的 C 标准库中的每个函数签名都保留给实现,以用作具有 extern "C" 和 extern "C++" 链接的函数签名,或用作全局命名空间中的命名空间范围的名称。
当它们没有明确包含在编译单元中时?
如果您完全使用标准库,则标准库的所有名称保留都有效。
如果您包含任何标准标头(或任何您无法控制其确切内容并因此可能包含标准标头的标头),那么您可能间接包含其他标准标头,包括从 C 继承的标头。