C ++에서 extern을 사용하는 경우


398

"Think in C ++"을 읽고 extern선언을 도입했습니다 . 예를 들면 다음과 같습니다.

extern int x;
extern float y;

나는 의미 (정의없는 선언)를 이해한다고 생각하지만 그것이 언제 유용한 지 궁금합니다.

누군가가 모범을 보일 수 있습니까?


1
extern여러 번 정의를 제공해야했습니다 . 다른 소스 파일의 테이블 만 정의 된 경우 Microsoft 도구에서 누락 된 기호에 대한 링크 오류가 발생했습니다. 문제는 테이블이었고 constC ++ 컴파일러 static가 번역 단위로 승격 시켰습니다 . 예를 들어 ariatab.cpp및을 참조하십시오 kalynatab.cpp.
jww

2
그리고 Nik의 대답은 C ++ 질문에 대답 한 것으로 보이는 유일한 사람이라고 생각합니다. 다른 사람들은 모두 C 질문에 빠져있는 것 같습니다.
jww

답변:


519

전역 변수가있을 때 유용합니다. 헤더에 전역 변수 의 존재 를 선언하여 헤더를 포함하는 각 소스 파일에 대해 알 수 있지만 소스 파일 중 하나에서 한 번만 "정의"하면됩니다.

명확히하기 위해를 사용 extern int x;하면 컴파일러에게 int라는 유형의 객체 x어딘가에 있다고 알립니다 . 존재하는 위치를 아는 것은 컴파일러 작업이 아니며, 유형과 이름 만 알고 있으면 사용 방법을 알 수 있습니다. 모든 소스 파일이 컴파일되면 링커는 x컴파일 된 소스 파일 중 하나에서 찾은 하나의 정의에 대한 모든 참조를 분석 합니다. x변수가 작동하려면 변수 정의에 "외부 링크"가 있어야합니다. 이는 기본적으로 함수 외부 (일반적으로 "파일 범위"라고 함) 외부에서 static키워드 없이 선언해야 함을 의미합니다 .

헤더:

#ifndef HEADER_H
#define HEADER_H

// any source file that includes this will be able to use "global_x"
extern int global_x;

void print_global_x();

#endif

소스 1 :

#include "header.h"

// since global_x still needs to be defined somewhere,
// we define it (for example) in this source file
int global_x;

int main()
{
    //set global_x here:
    global_x = 5;

    print_global_x();
}

소스 2 :

#include <iostream>
#include "header.h"

void print_global_x()
{
    //print global_x here:
    std::cout << global_x << std::endl;
}

15
감사합니다. 따라서 extern 키워드없이 헤더 파일에 전역 변수를 선언하면 헤더를 포함하는 소스 파일에 해당 변수가 표시되지 않습니까?
Aslan986

23
헤더에 전역 변수를 선언하면 안됩니다. 두 파일에 동일한 헤더 파일이 포함되어 있으면 링크되지 않습니다 (링커에서 "중복 심볼"에 대한 오류가 발생 함)
kuba

63
@ Aslan986 : 아니요. 더 나쁜 일이 있습니다. 헤더를 포함하는 각 소스 파일에는 고유 한 변수가 있으므로 각 소스 파일은 독립적으로 컴파일되지만 링커는 두 개의 소스 파일에 동일한 전역 식별자가 있으므로 불평 할 것입니다.
dreamlax

7
"extern"이라는 단어를 사용하지 않으면 변수가 존재합니다. "extern"을 사용할 때 "이것은 다른 곳에있을 수 있습니다"입니다. 정의 나 선언인지에 대해서는 대답하지 않는 것이 유감입니다. 항상이 두 가지에 대해 혼동되기 때문입니다.
쿠바

3
@CCJ : include guard는 그것을 포함하는 소스 파일에 대해서만 작동합니다. 동일한 헤더가 동일한 소스 파일 내에 두 번 포함되는 것을 중지합니다 (다른 헤더에도 포함되는 경우). 따라서 포함 가드를 사용하더라도 헤더를 포함하는 각 소스 파일은 여전히 ​​고유 한 정의를 갖습니다.
dreamlax 2016 년

172

몇 개의 모듈간에 변수를 공유 할 때 유용합니다. 한 모듈에서 정의하고 다른 모듈에서 extern을 사용하십시오.

예를 들면 다음과 같습니다.

file1.cpp에서 :

int global_int = 1;

file2.cpp에서 :

extern int global_int;
//in some function
cout << "global_int = " << global_int;

39
이 대답은 헤더 파일을 사용하지 않으므로 소수의 모듈간에 공유 할 때만 유용하다는 점을 분명히 나타 내기 때문에 허용 된 것보다 더 정확합니다. 큰 응용 프로그램의 경우 예를 들어 ConfigManager 클래스를 사용하는 것이 좋습니다.
Zac

1
네임 스페이스가 관련 global_int되어 있고 전역 네임 스페이스에있을 때 문제가 있습니까? 일부 네임 스페이스 섹션의 file2.cpp에서 사용하면 올바른 범위를 지정해야합니까? 즉namespace XYZ{ void foo(){ ::global_int++ } };
jxramos

8
@Zac : 반면에, 헤더에 전역 변수를 선언하지 않으면 실수로 실제로 정의 된 위치를 결정하기가 훨씬 더 어려워졌습니다. 일반적으로로 선언 된 전역 변수가 표시되면 abc.h로 정의 될 가능성이 높습니다 abc.cpp. 좋은 IDE는 항상 도움이되지만, 잘 구성된 코드는 항상 더 나은 솔루션입니다.
dreamlax

없이 externfile2.cpp에 여전히에 액세스 할 수 있습니다 global_int후 있습니다. 왜 내가 그것을해야합니까?
TomSawyer

62

그것은 모두 연계 에 관한 것 입니다.

이전 답변은에 대한 좋은 설명을 제공했습니다 extern.

그러나 중요한 점을 추가하고 싶습니다.

당신은에 대해 질문 extern에서 C ++ 하지에 C 때 사건에 대해 언급 아무 대답이없는 이유를 모르겠어요 extern함께 제공 const++ C이다.

C ++에서 const변수는 기본적으로 내부 링크가 있습니다 (C와 같지 않음).

따라서이 시나리오는 연결 오류가 발생합니다 .

출처 1 :

const int global = 255; //wrong way to make a definition of global const variable in C++

출처 2 :

extern const int global; //declaration

다음과 같아야합니다.

출처 1 :

extern const int global = 255; //a definition of global const variable in C++

출처 2 :

extern const int global; //declaration

2
정의 부분에 'extern'을 포함시키지 않고 c ++에서 작동하는 동안 왜 잘못 되었습니까?
최고 쉬프터

1
VIsual Studio에서 Visual Micro와의 연결 오류가 발생하지 않는 것 같습니다. 내가 무엇을 놓치고 있습니까?
Craig.Feied

1
@ lartist93 @ Craig.Feied 신중하게 다시 확인해야 할 수도 있습니다. 컴파일러가 연결 오류를 알리지 않더라도 두 소스의 두 객체가 모두 extern정의 없이 동일한 지 확인할 수 있습니까? global소스 2 의 값을 인쇄하면됩니다 .
Trevor

3
확인은 MSVS 2018가 경우 연결 오류 extern생략한다 const int global = 255;.
평균

13

전역 변수를 원할 때 유용합니다. 일부 소스 파일에서 전역 변수를 정의하고 해당 헤더 파일을 포함하는 모든 파일이 동일한 전역 변수를 볼 수 있도록 헤더 파일에서 extern을 선언합니다.


어쨌든 이것은 매우 OOP 소리가 들리지 않습니다. 싱글 톤 클래스 또는 로컬 정적 값을 반환하는 함수에 넣을 것입니다.
RzR
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.