内部和无联系之间的区别

zep*_*hon 10 c c++ scope linkage

请参阅同一翻译单元中的以下代码:

static int global_var; // file scope in C and global namespace scope in C++
                       // internal linkage
void f(void)
{
    static int local_var; // block scope in C and local scope in C++
                          // no linkage 
}
Run Code Online (Sandbox Code Playgroud)

我的理解是这样的:

  • 我可以从翻译单元的任何地方引用global_var,因为它具有全局范围.
  • 我只能在函数f中引用local_var,因为它具有局部范围.

我的问题:

  1. 与链接有关的两个变量有什么区别?
  2. 你能提供一个内部没有联系有所作为的例子,差异不仅来自范围吗?

编辑

在James Kanze的回答和评论之后,我现在能够构建一个示例,显示内部和无链接属性之间的区别:

static int i; // definition
              // static storage
              // internal linkage

void f(void)
{
    extern int i; // declaration
                  // refers to the static i at file scope
                  // note that even though the specifier is extern
                  // its linkage is intern (this is legal in both C/C++)
    {
        int i; // definition
               // automatic storage
               // no linkage
    }
}
Run Code Online (Sandbox Code Playgroud)


有些文章,在解释所涉及的概念做好:
- 在C和C++范围的区域
- 存储类标识符和存储时间
- 在C和C++联动

Jam*_*nze 8

第一:除了类型,变量还有三个其他特征:连接,范围和生命周期.所有四个属性都是正交的,但它们以语言表达的方式链接,并以某种方式进行交互.

关于链接:链接确实影响正在声明的符号,而不是对象本身.如果没有链接,则符号的所有声明都绑定到不同的对象,例如:

int
func()
{
    int i;
    {
        int i;
    }
}
Run Code Online (Sandbox Code Playgroud)

符号i没有链接,两个符号i绑定到两个不同的实体.一般来说,无论类型和生命周期如何,局部变量(在块作用域中声明的变量)和函数参数都没有链接.

内部和外部链接类似,因为符号的重复声明绑定到同一实体:内部链接仅在翻译单元内绑定,在整个程序外部绑定.所以给出:

static int i;   //  internal linkage...
Run Code Online (Sandbox Code Playgroud)

在几个翻译单元中,i绑定到每个翻译单元中的单独实体.没有静态,您有外部链接,并且所有i绑定到同一个实体.

请注意,这仅适用于命名空间范围; 作为非本地类成员的所有实体都具有外部链接.

这种类型有影响:const隐含的变量具有内部链接:

int const i = 42;    //  same as static int const i...
extern int const j = 42;    //  external linkage.
Run Code Online (Sandbox Code Playgroud)

最后,绑定到同一实体的所有声明必须声明它具有相同的类型.如果您在单个翻译单元中违反此规则(例如:

extern int i;
//   ...
double i;
Run Code Online (Sandbox Code Playgroud)

在相同的命名空间范围内),然后编译器应该抱怨.但是,如果两个声明位于不同的翻译单元中,则它是未定义的行为,谁知道会发生什么.(从理论上讲,链接器可能会抱怨,但大多数都没有.)

编辑:

还有一点:链接由第一个可以引用实体的声明决定.所以,如果我写:

static int i;

void
func()
{
    extern int i;
}
Run Code Online (Sandbox Code Playgroud)

两者都i指向具有内部链接的同一实体.(为什么人们会写第二个声明超出我的范围,但这是合法的.)