외부 연결과 내부 연결이란 무엇입니까?


337

외부 연결과 내부 연결 및 차이점을 이해하고 싶습니다.

나는 또한의 의미를 알고 싶다

const로 달리 선언되지 않는 한 변수는 기본적으로 내부적으로 링크됩니다 extern.

답변:


279

당신이 (구현 파일을 쓸 때 .cpp, .cxx등) 컴파일러는 생성 번역 단위를 . 이것은 구현의 소스 파일과 그 안에있는 모든 헤더 #include입니다.

내부 연결번역 단위의 범위에있는 모든 항목을 나타냅니다 .

외부 연결 은 특정 번역 단위를 넘어 존재하는 것들을 말합니다. 다시 말해, 모든 번역 단위 (또는 객체 파일)의 조합 인 전체 프로그램을 통해 액세스 할 수 있습니다 .


112
하나의 결함을 제외하고는 이것을 찬성했습니다. 번역 단위는 "어떻게 오브젝트 파일"이 아니며, 컴파일러 오브젝트 파일을 작성 하는 소스 코드입니다 .
sbi

4
@ FrankHB, 대답이 누락 된 "더 중요한 것"은 무엇입니까?
수학자

2
@Mathematician 늦어서 죄송합니다 ... 문제가 분명해야한다고 생각합니다 (언어의 정확성 외에). const변수의 규칙 과 그 목적 에 대한 질문 이 완전히 빠져 있기 때문에이 답변은 불완전 합니다.
FrankHB

294

으로 dudewat 말했다 외부 연결은 기호 (함수 나 전역 변수) 프로그램 및 전체에 액세스 할 수있는 의미 내부 가 하나 개에서만 액세스 할 수 있다는 연계 수단 번역 단위 .

externstatic키워드 를 사용하여 심볼의 연결을 명시 적으로 제어 할 수 있습니다 . 연계가 지정되지 않은 경우 기본 연계는 externconst기호 및 static(내부) const심볼에 대한 것 입니다.

// in namespace or global scope
int i; // extern by default
const int ci; // static by default
extern const int eci; // explicitly extern
static int si; // explicitly static

// the same goes for functions (but there are no const functions)
int foo(); // extern by default
static int bar(); // explicitly static 

사용하는 대신 주 static내부 연결을 위해 사용하는 것이 좋습니다 익명의 네임 스페이스 당신도 넣을 수 있습니다되는 class말이지. 익명 네임 스페이스에 대한 연결은 C ++ 98과 C ++ 11 사이에서 변경되었지만 가장 중요한 것은 다른 번역 단위에서 접근 할 수 없다는 것입니다.

namespace {
   int i; // external linkage but unreachable from other translation units.
   class invisible_to_others { };
}

11
"export"키워드의 구현은 'static'으로 선언 된 함수와 명명되지 않은 네임 스페이스에 선언 된 함수의 차이점을 강조했습니다. 최상의 번역을 위해 한 번역 단위에서 내보내기 키워드로 선언 된 함수 템플릿은 2 단계 조회의 결과로 다른 번역 단위의 명명되지 않은 네임 스페이스에 정의 된 함수를 참조 할 수 있습니다. ( ddj.com/showArticle.jhtml?articleID=184401584 )
Richard Corden

내가 다음을 수행하는 경우 : 1.cpp <code> const int ci; </ code> 2.cpp <code> extern const int ci; </ code>
Rajendra Uppal

2
@Rajenda 당신은 해결되지 않은 기호 오류를 보게 될 것입니다 (9 개월 동안 지연되어 죄송합니다.이 의견을 놓쳤습니다).
Motti

4
이 답변을 크게 향상시킬 수있는 정보 : 1) C ++ 11에서는 static이 더 이상 사용되지 않습니다. 2) C ++ 11의 익명 네임 스페이스 멤버는 기본적으로 내부 연결을 갖습니다. 참조 stackoverflow.com/questions/10832940/...
Klaim

2
"외부 연결이지만 다른 번역 단위에서 연결할 수 없음"이란 무엇입니까? 어떻게 접근 할 수 없지만 여전히 외부에있을 수 있습니까?
szx

101
  • 전역 변수에는 기본적으로 외부 연결 이 있습니다. extern다른 파일에 일치하는 선언 을 제공하여 범위를 포함하지 않는 범위로 확장 할 수 있습니다 .
  • 전역 변수의 범위는 선언 앞에 키워드를 붙여 선언을 포함하는 파일로 제한 할 수 있습니다 static. 이러한 변수는 내부 연결 이 있다고합니다 .

다음 예제를 고려하십시오.

1.cpp

void f(int i);
extern const int max = 10;
int n = 0;
int main()
{
    int a;
    //...
    f(a);
    //...
    f(a);
    //...
}
  1. 함수의 서명은 외부 연결을 가진 함수로 f선언합니다 (기본값). 이 파일의 정의는이 파일 또는 다른 번역 단위 (아래에 제공됨)에서 나중에 제공해야합니다.f
  2. max정수 상수로 정의됩니다. 상수의 기본 연결은 internal 입니다. 키워드와의 연결이 외부로 변경되었습니다 extern. 이제 max다른 파일에서 액세스 할 수 있습니다.
  3. n정수 변수로 정의됩니다. 함수 본문 외부에 정의 된 변수의 기본 연결은 external 입니다.

2.cpp

#include <iostream>
using namespace std;

extern const int max;
extern int n;
static float z = 0.0;

void f(int i)
{
    static int nCall = 0;
    int a;
    //...
    nCall++;
    n++;
    //...
    a = max * z;
    //...
    cout << "f() called " << nCall << " times." << endl;
}
  1. max외부 연결 을 갖도록 선언되었습니다 . max일부 파일 에 (외부 링크가있는)에 대한 일치하는 정의 가 나타나야합니다. (1.cpp에서와 같이)
  2. n외부 연결 을 갖도록 선언되었습니다 .
  3. z되고 정의 와 전역 변수로 내부 링크 .
  4. 의 정의는 function 호출에 대한 값을 유지하는 변수가되도록 nCall지정 nCall합니다 f(). 기본 자동 스토리지 클래스가있는 로컬 변수와 달리 nCall, 프로그램 시작시 한 번만 초기화되고을 호출 할 때마다 한 번만 초기화됩니다 f(). 스토리지 클래스 지정자는 static범위가 아닌 로컬 변수의 수명에 영향을줍니다.

주의 : 키워드 static는 두 가지 역할을합니다. 글로벌 변수의 정의에 사용될 때 내부 연결을 지정합니다 . 지역 변수의 정의에 사용될 때 변수의 수명이 함수의 지속 시간이 아닌 프로그램의 지속 시간이되도록 지정합니다.

희망이 도움이됩니다!


2
중요한 것은 로컬 변수의 정의에 사용될 때 static게으른 단일 초기화를 허용합니다 (글로벌 객체가 필요하지만 글로벌 생성 순서 문제로 인해 생성되는 시점을 제어해야하며 동적으로 할당 할 수없는 경우 유용해야 함) 사용하여 new암시 적으로,이) C ++를 사용하는 임베디드 시스템에 문제가 주로, 더 깊이 초기화 제도가 해당 개체에 필요한 것 이상이 될 수도있다.
JAB

1
아주 좋은 시험, 내 하루를했다.
Blood-HaZaRd

28

'C'와 관련하여 (정적 키워드는 'C'와 'C ++'사이에서 다른 의미를 갖기 때문에)

'C'의 다른 범위에 대해 이야기 할 수 있습니다

범위 : 기본적으로 얼마나 오래 볼 수 있고 얼마나 멀리 있습니다.

  1. 지역 변수 : 범위는 함수 안에 만 있습니다. RAM의 STACK 영역에 있습니다. 즉, 함수가 호출 될 때마다 함수 인수를 포함하여 해당 함수의 일부인 모든 변수가 새로 만들어 져서 컨트롤이 함수를 벗어나면 소멸됩니다. (함수가 반환 될 때마다 스택이 플러시되므로)

  2. 정적 변수 : 이것의 범위는 파일입니다.
    선언 된 파일의 모든 위치에 액세스 할 수 있습니다 . RAM의 DATA 세그먼트에 상주합니다. 파일 내부에서만 액세스 할 수 있으므로 내부 링크가 가능합니다. 모든
    다른 파일이 변수를 볼 수 없습니다. 사실 STATIC 키워드는
    'C'에 일정 수준의 데이터 또는 함수 숨기기를 도입 할 수있는 유일한 방법입니다.

  3. 전역 변수 : 이것의 범위는 전체 응용 프로그램을위한 것입니다. 응용 프로그램의 모든 곳에서 액세스 할 수 있습니다. 전역 변수도 DATA 세그먼트에 상주합니다. 응용 프로그램의 모든 위치에 액세스 할 수 있으므로 EXTERNAL Linkage

기본적으로 모든 기능은 전역입니다. 파일 외부에서 일부 함수를 숨겨야하는 경우 정적 키워드를 함수 앞에 붙일 수 있습니다. :-)


12
@Libin : 1) 로컬 변수는 스택에있을 필요가 없습니다-일반적으로 스택에 있지만 레지스터에있을 수 있으며 ARM 환경에서는 스택보다 레지스터에 더 자주 있습니다 (일부 요인에 따라-호출 수준, 숫자)
agurs

4
@Libin : 1) 'flush'를 덮어 쓰는 것으로 간주하면 잘못되었습니다. 스택 포인터가 다른 위치로 이동되었습니다. '이전에는 유효한 로컬 변수'가 '플러시'/ 삭제되지 않습니다. 가변 범위를 저장 기간과 혼합합니다. 범위는 var에 액세스 할 수있는 위치를 알려줍니다. 저장 기간은 그것이 존재하는 기간을 알려줍니다. 정적 저장 시간으로 지역 변수를 가질 수 있습니다. 그것은 "영원히"살지만 그것이 선언 된 함수에서 액세스 할 수 있다는 것을 의미합니다.
Artur

2
부정확 한 개념과 명백한 오해에 대한 공감. 엄밀히 말하면 C에 정의 된 "전역"또는 "변수"(명사)는 없습니다. "전역 변수"보다는 "파일 범위 개체"를 참조하고 싶지만 "범위"(C에서 의 식별자 속성 )이 말이 안됩니다. (두 용어는 C ++에서 약간 다르게 다른 의미로 정의됩니다.)
FrankHB

내가 생각 @Artur you'd는 "잊고 "에서 " 영원히 그것이 사는 의미" "하지만이 선언되는 함수에서 (만)에 액세스 할 수 있습니다. "-이 때문에 나는 점에하고 싶은, 중요한 세부 사항입니다 명시 적으로.
RobertS는

14

질문에 대해 이야기하기 전에 번역 단위 , 프로그램 및 C ++의 기본 개념 (실제로 연결은 일반적으로 그중 하나임) 이라는 용어를 정확하게 아는 것이 좋습니다 . 또한 범위 가 무엇인지 알아야합니다 .

몇 가지 핵심 사항을 강조하겠습니다. 이전 답변에서 누락 된 사람들.

연결이름 의 속성이며 선언에 의해 소개됩니다 . 다른 이름은 동일한 개체 (일반적으로 개체 또는 함수)를 나타낼 수 있습니다 . 따라서 엔터티의 연결 에 대해 말하는 것은 일반적으로 엔터티가 특정 선언 (일반적으로 하나의 선언)에서 고유 한 이름으로 만 참조된다고 확신하지 않는 한 무의미합니다.

목적은 실체이지만, 변수는 아니다. 변수의 연결에 대해 이야기하는 동안 실제로 표시된 엔티티 (특정 선언에 의해 도입 된)의 이름이 관련됩니다. 이름의 연결은 연결 없음, 내부 연결 또는 외부 연결 중 하나에 속합니다.

다른 번역 단위는 헤더 / 소스 파일 (예, 표준 문구) 포함으로 동일한 선언을 공유 할 수 있습니다. 따라서 다른 번역 단위에서 동일한 이름을 참조 할 수 있습니다. 선언 된 이름에 외부 연결이있는 경우 해당 이름으로 참조 된 엔티티의 ID도 공유됩니다. 선언 된 이름에 내부 연결이있는 경우 다른 번역 단위에서 동일한 이름이 다른 엔터티를 나타내지 만 동일한 번역 단위의 다른 범위에서 엔터티를 참조 할 수 있습니다. 이름에 연결이없는 경우 다른 범위의 엔터티를 참조 할 수 없습니다.

(죄송합니다 ... 입력 한 내용이 다소 표준 문구를 반복 하는 것으로 나타났습니다 ...)

언어 사양에 포함되지 않는 다른 혼란스러운 점들도 있습니다.

  1. 가시성 (이름). 또한 선언 된 이름의 속성이지만 linkage와 다른 의미를 갖습니다 .
  2. 가시성 (부작용) . 이것은이 주제와 관련이 없습니다.
  3. 가시성 (기호). 이 개념은 실제 구현에서 사용할 수 있습니다 . 그러한 구현들에서, 객체 (이진) 코드에서 특정 가시성을 갖는 심볼은 일반적으로 소스 (C ++) 코드에서 동일한 특정 링크를 갖는 엔티티 정의로부터 매핑 된 대상이다. 그러나 일대일 보장은 아닙니다. 예를 들어, 동적 라이브러리 이미지의 기호는 소스 코드에서 내부적으로 해당 이미지에서만 공유되도록 지정할 수 있습니다 (일부 확장 프로그램과 함께 __attribute__또는__declspec) 또는 컴파일러 옵션을 사용할 수 있으며 이미지가 전체 프로그램 또는 번역 단위에서 번역 된 객체 파일이 아니므로 표준 개념으로 정확하게 설명 할 수 없습니다. C ++에서 symbol은 규범적인 용어가 아니기 때문에 관련 방언의 확장이 널리 채택되어 있어도 구현 세부 사항 일뿐입니다.
  4. 접근성. C ++에서 이것은 일반적 으로 클래스 멤버 또는 기본 클래스의 속성에 관한 것으로, 주제와 관련이없는 다른 개념입니다.
  5. 글로벌 C ++에서 "글로벌"은 글로벌 네임 스페이스 또는 글로벌 네임 스페이스 범위를 의미합니다. 후자는 C 언어의 파일 범위 와 거의 같습니다 . C와 C ++에서 연결 (linkage)과 같은 범위는 식별자 (C) 또는 이름 (C ++)과 밀접하게 관련되어 있지만 범위와는 아무런 관련이 없습니다.

네임 스페이스 범위 const변수연결 규칙은 특별합니다 (특히 constC 언어로 파일 범위에서 선언 된 객체 와 다르며 식별자 연결이라는 개념이 있습니다). ODR 은 C ++에 의해 시행 되므로 함수를 제외하고 전체 프로그램에서 동일한 변수 또는 함수의 정의를 두 개 이상 유지하지 않는 것이 중요 inline합니다 . 특별한 규칙이 없다면 const, 여러 번역 단위 (또는 하나의 번역 단위로 여러 번 포함 된 헤더 또는 소스 파일 (종종 "헤더 파일")에 const이니셜 라이저 (예 :)가 포함 된 가장 간단한 변수 선언 = xxx, 그러나 드물게) 프로그램에서 ODR을 위반하여 사용하게됩니다.const 일부 객체와 유사한 매크로를 대체 할 수 없습니다.


3
이 답변은 매우 능숙하게 들리고 매우 정확할 수 있지만 (나는 그것을 판단 할 수 없습니다) 대부분 언어 사양을 직접 읽는 대신이 질문을 찾는 많은 사람들이 원하는만큼 이해하기 어려울 것입니다. 적어도 내 요구에 대해서는 받아 들일만한 대답을 고수하지만 여전히 언어 사양에 대한 작은 통찰력을 주신 것에 대해 감사드립니다. 👍🏻
wedi

8

C ++의 내부 및 외부 링크 는 명확하고 간결한 설명을 제공 한다고 생각 합니다.

변환 단위는 구현 (.c / .cpp) 파일 및 포함 된 모든 헤더 (.h / .hpp) 파일을 나타냅니다. 이러한 변환 단위 내의 개체 나 함수에 내부 연결이있는 경우 해당 변환 기호 내에서만 링커가 해당 심볼을 볼 수 있습니다. 개체 나 함수에 외부 연결이있는 경우 링커는 다른 변환 단위를 처리 할 때이를 볼 수도 있습니다. 글로벌 네임 스페이스에서 사용될 때 static 키워드는 심볼에 내부 링크가 있도록합니다. extern 키워드는 외부 링크가있는 심볼을 생성합니다.

컴파일러는 기본적으로 심볼 연결을 다음과 같이 지정합니다.

비 const 전역 변수에는 기본적으로 외부 연결이 있습니다
Const 전역 변수에는 기본적으로 내부 연결이 있습니다
함수에는 기본적으로 외부 연결이 있습니다


6

연결은 식별자가 다른 변환 단위로 표시 되더라도 동일한 이름을 가진 식별자가 동일한 객체, 함수 또는 다른 엔터티를 참조하는지 여부를 결정합니다. 식별자의 연결은 선언 방법에 따라 다릅니다. 연계에는 세 가지 유형이 있습니다.

  1. 내부 연결 : 식별자는 번역 단위 내에서만 볼 수 있습니다.
  2. 외부 연결 : 다른 번역 단위에서 식별자를 볼 수 있습니다.
  3. 연계 없음 : 식별자는 정의 된 범위에서만 볼 수 있습니다. 연결은 범위에 영향을 미치지 않습니다

C ++ 전용 : C ++과 비 C ++ 코드 단편 ( 언어 연계 라고 함)을 연계 할 수도 있습니다.

출처 : IBM 프로그램 연계


5

원래

  • extern linkage 변수는 모든 파일에서 볼 수 있습니다
  • internal linkage 변수는 단일 파일에서 볼 수 있습니다.

설명 : const 변수는 extern으로 달리 선언되지 않는 한 기본적으로 내부적으로 링크됩니다.

  1. 기본적으로 전역 변수는 external linkage
  2. 그러나 const전역 변수는internal linkage
  3. 추가로 extern const전역 변수는external linkage

C ++의 링키지에 대한 꽤 좋은 자료

http://www.goldsborough.me/c/c++/linker/2016/03/30/19-34-25-internal_and_external_linkage_in_c++/


1

C ++에서

파일 범위에 있고 클래스 나 함수 안에 중첩되지 않은 모든 변수는 프로그램의 모든 변환 단위에서 볼 수 있습니다. 링크 타임에 이름이 해당 번역 단위 외부의 모든 링커에 표시되므로 외부 링크 라고 합니다.

전역 변수와 일반 함수에는 외부 연결이 있습니다.

파일 범위의 정적 객체 또는 함수 이름은 번역 단위에 로컬입니다. 이를 내부 연계 라고합니다

링크는 링크 /로드시 주소가있는 요소 만 나타냅니다. 따라서 클래스 선언과 지역 변수에는 연결이 없습니다.


const 전역 변수에는 내부 연결이 있습니다.
Blood-HaZaRd
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.