本文介绍了各种常量/静态变量的链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个关于从以下变量的链接的问题。通过C ++ 03的7.1.1 / 7的例子和实验编译器(Comeau,Clang和GCC),我来到以下连接类型:


  1. 首先 static ,然后 extern


    $ b b

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

    :(a)意味着内部联系。和(b)也暗示内部链接,因为名称a被声明为静态的(通过(a))。


  2. 首先 extern ,然后 static / p>

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

    首先,(c)意味着外部链接。但是(d)意味着内部链接,因为名称b由(d)声明为静态的。根据7.1.1 / 7,这是无效的,因为隐含的链接不一致。


  3. 首先 const ,然后 extern / p>

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

    首先,因为它是const,既没有声明显式extern也没有以前暗示的外部链接。和(f)应该暗示extern链接和一个错误,因为它明确声明的名称extern,但编译器保持它内部! 为什么这样?这是我的问题。


  4. c $ c>,然后 const

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

    现在,我们明确声明extern。和(h)也暗示外部链接,因为(g)明确声明extern。







我实验性地发现了3和4的链接以下模板(第二个参数需要具有外部链接)

 模板< typename T,T& struct ensure {}; 

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






strong>与的讨论结果证明是相当有成效的,并且显示有两种可能的解释: 3.5 / 3 ,其中重要的项目符号为

如果我们看看点(f)
$ b


  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;在遇到第一个声明时,我们注意到 pi1 >被显式声明为 const ,但是既没有明确声明 extern 也没有声明有外部链接。这匹配3.5 / 2的选项之一,因此 pi1 有内部链接。



遇到第二个声明ask是 pi1 显式声明为 const 但未明确声明的对象的名称或[... blah ...]。我认为这是因为它是在(e)点宣布的。当然,它不是声明的方式无处不在,但以相同的方式 a 是一个对象的名称声明 static 当我们考虑 extern int a; 声明时,即使它没有声明 static 无处不在。这对我来说意味着声明(f)并不意味着与声明(e)有不同的联系。


I have a few questions about the linkage from the following variables. By examples of 7.1.1/7 of C++03 and experimenting with compilers (Comeau, Clang and GCC), I came to the following linkage kinds:

  1. First static, then extern

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

    It's clear to me with accordance to section 3.5: (a) implies internal linkage. And (b) also implies internal linkage, because the name "a" is declared static (by (a)).

  2. First extern, then static

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

    First, (c) implies external linkage. But (d) implies internal linkage because the name "b" is declared static by (d). This is invalid according to 7.1.1/7, since the linkage implied is not consistent.

  3. First const, then extern

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

    First, (e) implies internal linkage, because it is const, and neither declared explicit extern nor previously implied external linkage. And (f) should imply extern linkage and be an error, because it explicitly declares the name extern, but the compilers keep it internal! Why so? That's my question.

  4. First extern, then const

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

    Now, (g) implies external linkage because we explicitly declared extern. And (h) also implies external linkage because (g) explicitly declared extern.


I have experimentally found out the linkage for 3 and 4 with the following template (the second argument is required to have external linkage)

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

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


Summary: The Discussion with Charles Bailey turned out to be quite fruitful and showed there are two possible interpretations of 3.5/3, where the important bullet point reads

If we look at point (f), then the two interpretations come to different conclusions, as shown below

  1. The first interpretation notes that pi1 is declared const but is also declared extern. The variable has thus external linkage.

  2. The second interpretation interpretes both occurences of "declared" to refer to the same declaration. In this way, it means that it is declared const, but not extern const. We note that (e) is declared const and not extern const, thus we give pi1 internal linkage.

Now what interpretation is correct? I can't determine from that wording, but compilers seem to interpret this the second way. In particular, if we take the first interpretation, then the last quoted part of 3.5/3 would be superfluous, because there would be no valid scenario in which a name would be declared const and previously declared with external linkage but without an explicit extern.

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

My interpretation is as follows. When considering the linkage of a name we consider previous declarations as well as the one being interpreted at this point in the parse. This is why static int a; extern int a; is OK, but extern int b; static int b; is not.

On encountering the first declaration we note that pi1 is explicitly declared const but neither explicitly declared extern nor previously declared to have external linkage. This matches one of the options of 3.5/2 therefore pi1 has internal linkage.

On encountering the second declaration we ask is pi1 the name of an object that is explicitly declared const but neither explicitly declared extern nor [... blah ...]. I contend that it is because it was so declared at point (e). Sure, it isn't declared that way everywhere but in the same way a was the name of an object declared static when we were considering the extern int a; declaration even though it wasn't declared static everywhere. This, to me, means that the declaration (f) doesn't imply a different linkage from declaration (e).

这篇关于各种常量/静态变量的链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 10:08