c++ - 各种常量/静态变量的链接

标签 c++ static extern linkage

我对以下变量的联系有一些疑问。通过 C++03 的 7.1.1/7 示例和编译器(Comeau、Clang 和 GCC)的实验,我得出以下链接类型:

  1. 首先是static,然后是extern

    static int a; // (a)
    extern int a; // (b) valid, 'a' still internal
    

    根据第 3.5 节,我很清楚:(a) 暗示内部联系。并且 (b) 也意味着内部链接,因为名称“a”被声明为静态的(由 (a))。

  2. 首先是extern,然后是static

    extern int b; // (c)
    static int b; // (d) invalid!
    

    首先,(c) 表示外部链接。但是(d)暗示了内部链接,因为名称“b”被(d)声明为静态的。根据 7.1.1/7,这是无效的,因为隐含的链接不一致。

  3. 首先是const,然后是extern

    const double pi1 = 3.14; // (e)
    extern const double pi1; // (f) valid and 'pi1' is internal
    

    首先,(e) 隐含内部链接,因为它是常量,既没有声明为显式外部链接,也没有先前隐含外部链接。并且 (f) 应该暗示外部链接并且是一个错误,因为它显式声明了名称 extern,但编译器将其保留在内部! 为什么会这样? 这是我的问题。

  4. 首先是extern,然后是const

    extern const double pi2; // (g)
    const double pi2 = 3.14; // (h) valid and 'pi2' is external
    

    现在,(g) 意味着外部链接,因为我们明确声明了 extern。并且 (h) 也暗示外部链接,因为 (g) 显式声明为 extern。


我已经通过以下模板实验找到了 3 和 4 的链接(第二个参数需要有外部链接)

template<typename T, T&> struct ensure { };

ensure<const double, pi1> e1; // failed
ensure<const double, pi2> e2; // succeeded

总结:Charles Bailey的讨论结果非常有成果,表明 3.5/3 有两种可能的解释,其中重要的要点是

A name having namespace scope (3.3.5) has internal linkage if it is the name of

  • an object or reference that is explicitly declared const and neither explicitly declared extern nor previously declared to have external linkage;

如果我们看点(f),那么两种解释会得出不同的结论,如下所示

  1. 第一种解释指出 pi1 被声明为 const 但也被声明为 extern。因此,该变量具有外部 链接。

  2. 第二种解释将两次出现的“已声明”解释为指代同一声明。这样,就意味着它被声明为const,而不是extern const。我们注意到 (e) 被声明为 const 而不是 extern const,因此我们给 pi1 内部链接。

现在什么解释是正确的?我无法从该措辞中确定,但编译器似乎以第二种方式解释这一点。特别是,如果我们采用第一种解释,那么 3.5/3 中最后引用的部分将是多余的,因为没有有效的场景可以将名称声明为 const 并且之前使用外部链接声明但没有明确的 extern

最佳答案

const double pi1 = 3.14; // (e)
extern const double pi1; // (f) valid and 'pi1' is internal

我的解释如下。在考虑名称的链接时,我们会考虑先前的声明以及在解析中此时正在解释的声明。这就是为什么 static int a; extern int a; 可以,但是 extern int b; static int b; 不是。

在遇到第一个声明时,我们注意到 pi1 被显式声明为 const 但既没有显式声明 extern 也没有先前声明为具有外部链接。这与 3.5/2 的选项之一匹配,因此 pi1 具有内部链接。

在遇到第二个声明时,我们要求 pi1 显式声明 const 但既未显式声明 extern 也未显式声明 [ ...等等...]。我认为这是因为它是在 (e) 点如此宣布的。当然,并不是所有地方都这样声明,但是当我们考虑 extern int a; 时,a 是声明为 static 的对象的名称; 声明,即使它没有在任何地方声明为 static。对我来说,这意味着声明 (f) 并不意味着与声明 (e) 不同的联系。

关于c++ - 各种常量/静态变量的链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3538807/

相关文章:

c++ - lstd++ 和 extern - 从 C 调用 C++

c++ - 外部关键字和未解析的外部符号

ios - 全局可用值ios7

c++ - 在 C++ 中将 HWND 转换为十六进制字符串

c++ - 使用 std::unique_ptr 将所有权转移到函数

c++ - 静态类 C++

angular - 类型 '() => Observable<any>' 不可分配给类型 '() => Observable<any>'

c++ - 这些错误是什么意思? ISOC++禁止分配数组

c++ - Linux 和 Windows 返回值不同的原因是什么,如何解决?

PHP - 回调函数中的 self、static 或 $this