首页 > 解决方案 > 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>...\ucrt\time.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>...\ucrt\time.h(518,42): message : class 'time' is hidden by a non-type declaration of 'time' here

所以问题是:当 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:%d\n", a.h, a.min, a.sec);
    return 0;
}

标签: c++clanguage-lawyerlibc

解决方案


[extern.names]

3使用外部链接声明的 C 标准库中的每个名称都保留给实现,以用作具有外部“C”链接的名称,无论是在命名空间 std 中还是在全局命名空间中。

请注意,本段保留名称本身。因此,全局命名空间中的别名time违反了这个约定。


推荐阅读