C ++ 컴파일러는 extern 변수를 어떻게 찾습니까?


15

이 프로그램을 g ++ 및 clang ++로 컴파일합니다. 차이점은 다음과 같습니다.
g ++는 1을 인쇄하지만 clang ++는 2를 인쇄합니다. g ++ : extern varible은 가장 짧은 범위에서 정의 된
것 같습니다
.
clang ++ : extern varible은 가장 짧은 전역 범위에서 정의됩니다.

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;
  }
}

other.cpp

int i;

버전 : g ++ : 7.4.0 / clang ++ : 10.0.0
컴파일 : $ (CXX) main.cpp other.cpp -o extern.exe


4
컴파일러는 외부 참조가있는 변수로 표시하는 것을 제외하고 extern으로 아무것도하지 않습니다. 링커는 모든 컴파일 된 객체 파일 간의 링크를 해결하려고합니다.
뿌림

훌륭한 (이상한 경우) 질문! 코드를 사용 MSVC하고 clang-cl(둘 다 제공 2), 둘 다 extern int i완전히 무시한 것 같습니다 . other.cpp파일에 링크하지 않아도 프로그램이 빌드되고 실행됩니다.
Adrian Mole

1
@SPlatten 아마도 링커가에 대한 참조를 '해결'할 필요 i가 없으므로 시도하지 않습니다.
Adrian Mole

3
관련된 오래된 일시 중단 된 GCC 버그는 여기 에서 찾을 수 있으며 해당하는 오픈 Clang 버그는 여기에서
월넛

답변:


11

[basic.link/7] 은 표준의 관련 부분이어야합니다. 현재 초안에서는 다음과 같이 말합니다.

블록 범위에서 선언 된 함수의 이름과 블록 범위 extern선언으로 선언 된 변수의 이름 은 연결되어 있습니다. 이러한 선언이 명명 된 모듈에 첨부되면 프로그램이 잘못 구성됩니다. 링크가있는 엔터티의 가시적 선언이있는 경우 가장 안쪽의 네임 스페이스 범위 외부에 선언 된 엔터티를 무시하면 두 범위의 선언이 동일한 선언 영역에 나타나면 블록 범위 선언이 (잘못된 형식으로) 다시 선언됩니다. 블록 범위 선언은 동일한 엔티티를 선언하고 이전 선언의 링크를 수신합니다. 일치하는 엔티티가 둘 이상인 경우 프로그램이 잘못 구성됩니다. 그렇지 않으면 일치하는 엔티티가 없으면 블록 범위 엔티티가 외부 링크를 수신합니다.번역 단위 내에서 동일한 엔터티가 내부 및 외부 연결로 선언 된 경우 프로그램이 잘못 구성됩니다.

다음 예제는 귀하의 경우와 거의 정확히 일치합니다.

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에 외부 연계가 제공되므로 프로그램이 잘못 작성됩니다.


이 예제의 프로그램은 외부 링크가 정의 된 i가 없기 때문에 형식이 잘못되었습니다 . OP의 예에는 해당되지 않습니다.
n. '대명사'm.

3
@n. '대명사입니다. 그러나이 규칙은 번역 단위에 적용됩니다. 번역 단위 내에서 동일한 엔터티가 내부 및 외부 연결로 선언 된 경우 프로그램이 잘못 구성됩니다. .
다니엘 랭거

2
대답은 C ++ 17 이상에만 적용됩니다 . CWG 문제 426 해결을 참조하십시오 . 그 변경 전에 GCC가 올바른 것 같습니다.
호두

좋아, 표준의 이전 판을 읽는 것처럼 보입니다.
n. '대명사'm.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.