Как компиляторы c ++ находят переменную extern? - PullRequest
15 голосов
/ 07 января 2020

Я компилирую эту программу с помощью g ++ и clang ++. Есть разница:
g ++ печатает 1, но clang ++ печатает 2.
Кажется, что
g ++: внешняя переменная определена в кратчайшей области.
clang ++: внешняя переменная определена в кратчайшая глобальная область.

Имеет ли C ++ spe c какие-либо технические характеристики по этому поводу?

main. cpp

#include <iostream>
static int i;
static int *p = &i;

int main() {
  int i;
  {
    extern int i;
    i = 1;
    *p = 2;
    std::cout << i << std::endl;
  }
}

прочее. cpp

int i;

версия: g ++: 7.4.0 / clang ++: 10.0.0
компиляция: $ (CXX) main. cpp other. cpp -o extern.exe

1 Ответ

11 голосов
/ 07 января 2020

[basi c .link / 7] должно быть соответствующей частью стандарта. В текущем черновике написано:

Имя функции, объявленной в области видимости блока, и имя переменной, объявленной в области видимости блока extern, имеют связь. Если такая декларация прикреплена к названному модулю, программа является некорректной. Если существует видимое объявление объекта со связью, игнорирующее объекты, объявленные вне самой внутренней охватывающей области пространства имен, так что объявление области блока будет (возможно, неправильно сформированным) переобъявлением, если эти два объявления появились в одной и той же декларативной области, Объявление блока блока объявляет ту же сущность и получает связь с предыдущим объявлением. Если существует более одного такого совпадающего объекта, программа является некорректной. В противном случае, если соответствующий объект не найден, объект области блока получает внешнюю связь. Если в единице перевода одна и та же сущность объявлена ​​как с внутренней, так и с внешней связью, программа плохо сформирована.

Обратите внимание, что следующий пример почти точно соответствует вашему case:

static void f();
extern "C" void h();
static int i = 0;               // #1
void g() {
  extern void f();              // internal linkage
  extern void h();              // C language linkage
  int i;                        // #2: i has no linkage
  {
    extern void f();            // internal linkage
    extern int i;               // #3: external linkage, ill-formed
  }
}

Итак, программа должна быть некорректной. Объяснение приведено ниже примера:

Без объявления в строке # 2 объявление в строке # 3 будет связано с объявлением в строке # 1. Поскольку объявление с внутренней связью скрыто, # 3 получает внешнюю связь, что делает программу плохо сформированной.

...