6

我对以下变量的联系有一些疑问。通过 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) 暗示了内部链接,因为它是 const 的,既没有显式声明 extern,也没有先前暗示的外部链接。并且 (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

总结:查尔斯·贝利的讨论结果非常有成果,并表明有两种可能的解释3.5/3,其中重要的要点是

具有命名空间范围 (3.3.5) 的名称如果是

  • 显式声明为 const 且既未显式声明 extern 也未先前声明具有外部链接的对象或引用;

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

  1. 第一个解释说明pi1是声明const的,但也是声明extern的。因此,该变量具有外部联系。

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

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

4

3 回答 3

4
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也没有 [... blah ...] 的对象的名称。我认为这是因为它在 (e) 点如此宣布。当然,它并不是到处都这样声明的,但是当我们考虑a声明时,它以同样的方式声明的对象的名称,即使它没有在任何地方声明。对我来说,这意味着声明 (f) 并不意味着与声明 (e) 有不同的联系。staticextern int a;static

于 2010-08-22T00:55:37.723 回答
0

我认为在#3中您的分析出错了。据我所知,const这并不意味着任何联系。我不确定您如何得出编译器使链接成为内部的结论。大多数编译器将(作为一种优化)将所有对 const 变量的引用替换为它被初始化的值,因此该符号可能根本不会出现在代码中。

即使您没有这样做,从 #1 中也可以清楚地看出,如果随后使用extern关键字声明了具有内部链接的某些内容,则它仍然具有内部链接。所以我不知道你为什么会期待一个错误。

如果const隐含内部链接,那么 #4 应该是一个错误,原因与 #2 相同。

于 2010-08-21T21:12:08.683 回答
0

根据第 7.1.1/7 节“给定实体的连续声明所暗示的链接应一致”,将 (e) 和 (f) 置于同一命名空间范围内是完全无效的。

此规则需要诊断。

但是,至少 Comeau Online 没有诊断出违规行为。

干杯&hth.,

编辑:嘿嘿,我查阅了DR 426,正如此处另一个答案中提到的那样,似乎那些起草提议的决议,使其成为 UB 而不是可诊断的人,并不知道 §7.1.1/7。我不会对这个问题发表评论,甚至不会在 comp.std.c++ 中提出它,因为我发现标准化工作对我来说过于政治化和荒谬(胡说八道)。但无论哪种方式,代码都是无效的。

于 2010-10-29T06:02:36.343 回答