【问题标题】:Linkage of function declared as `extern` in block scope according to the C++17 standard draft根据 C++17 标准草案在块范围内声明为“extern”的函数的链接
【发布时间】:2017-02-01 11:42:53
【问题描述】:

来自C++17 Standard Draft§ 3.5.6

块作用域中声明的函数名和块作用域extern声明的变量名 声明有联系。 如果存在具有相同名称的链接的实体的可见声明,并且 类型,忽略在最里面的封闭命名空间范围之外声明的实体,块范围声明 声明同一个实体并接收前一个声明的链接。如果有不止一个这样的 匹配实体,程序格式错误。否则,如果没有找到匹配的实体,则块范围实体 接收外部链接

另外在标准中提供了一个例子:

static void f();
static int i = 0;              // #1
void g() {
    extern void f();          // internal linkage
    int i;                    // #2 i has no linkage
    {
        extern void f();      // internal linkage
        extern int i;         // #3 external linkage
    }
}

第三个函数声明extern void f()是否接收:

  • external 链接(由于前面的 extern void f() 声明)
  • internal 链接(因为上面块作用域中 f() 的第二个声明接收来自 :: 全局命名空间中 f() 声明的内部链接)
  • 或者它是不正确的,因为有多个这样的匹配 实体”?

编辑

ma​​in.cpp

#include <iostream>

extern void g();
void f() { std::cout << "main f() called" << std::endl; }

int main(){
    g(); 
    return 0; 
}  

test.cpp

#include <iostream>

static void f() { std::cout << " test f() called" << std::endl; }
void g() {
    extern void f(); 
    {
        extern void f(); 
        f(); 
    }
}

g()main.cppmain() 函数中被调用。
gcc 5.4.0编译

g++ -std=c++14 -Wall main.cpp test.cpp

打印:

主 f() 调用

因此,gcc 显然将来自 g() 内的 f() 调用与 external 链接(调用 main.cpp 文件中提供的定义)。标准示例中的注释是错误的(#3 的函数声明没有内部链接)或者是来自gcc 的编译器错误。

【问题讨论】:

  • “忽略在最里面的封闭 namespace 范围之外声明的实体”。关键词是“命名空间”。示例中的所有标识符都在同一个命名空间中。
  • @AlexP 为什么来自#3 的变量i 然后具有external 链接而不是static 链接,如#1 中声明的那样?
  • "在这个程序中有三个名为i的对象。在全局范围内(第1行)声明引入的具有内部链接的对象,具有自动存储时长的对象第 2 行的声明没有引入链接,并且第 3 行的声明引入了具有静态存储持续时间和外部链接的对象。”请参阅第 3.5.9 节,为什么 extern int istatic int i 不同 i
  • @AlexP 好吧,我明白了。有点棘手。因此,所有三个i 都表示三个不同的变量,所有f() 都表示同一个函数?用g++ 5.4.0 编译它为变量提供了正确的行为,但是对上面#3 的函数f() 的调用调用了在其他翻译单元中提供的定义。是来自gcc 的错误还是最近草稿中的定义发生了变化?
  • @SebTu:C++11 的草案 n3337 中的定义已经相同

标签: c++ language-lawyer iso c++17 linkage


【解决方案1】:

我不明白你的困惑。最里面的封闭命名空间范围是global namespace;第一个和第二个声明在类型和名称上匹配,因此外部块范围声明仅继承全局声明的链接(由于static 说明符,这是内部的)。第二个块范围声明与第一个相关联;你明白了。

【讨论】:

    猜你喜欢
    • 2018-12-28
    • 1970-01-01
    • 2011-11-06
    • 2015-04-12
    • 1970-01-01
    • 2020-07-31
    • 2011-06-12
    • 2016-05-05
    相关资源
    最近更新 更多