2017-01-12 9 views
3

다음은 두 개의 개별 파일 Test1.c와 Test2.c로 작성된 두 개의 별도 코드입니다. 어떤 파일에서든지 extern 키워드를 사용하고 있지 않습니다. GCC를 사용하여 코드를 컴파일왜 'extern'을 사용하지 않더라도 GCC가 두 파일을 컴파일하고 연결하는 이유는 무엇입니까?

//Test1.c 
#include <stdio.h> 

int a = 1; 
int main() 
{ 
    printf("test1 - a val = %d\n",a); 
    fn(); 
    printf("After Return : %d",a); 
} 

//Test2.c 
#include <stdio.h> 

int a; 
int fn() 
{ 
    printf("test2 - a val = %d\n",a); 
    a++; 
} 

I : 이것은 다음과 같은 출력을 생성

gcc Test1.c Test2.c 

:

test1 - a val = 1 
test2 - a val = 1 

나는 두 코드 가변 a 주소를 인쇄하려고. 주소도 같습니다.

지금은 다음 한 질문 : gcc 자동 컴파일 및 링크도 extern 경우 하는가

  1. 를 사용하지 ?? 여기 분명히 gcc 내부적으로 나는이 두 파일을 함께 컴파일하고 있습니다.
  2. 이 동작은/않고 extern 키워드는 컴파일러 종속적입니까?
+0

엄격하게 준수하지는 않습니다. 표준의 Annex J에 문서화 된 '일반적인 확장'입니다. [C에서 소스 파일간에 변수를 공유하는 데 'extern'을 사용하려면 어떻게합니까?] (http://stackoverflow.com/questions/1433204/)의 '전역 변수를 정의하는 좋은 방법'섹션을 참조하십시오. –

+0

다음으로 컴파일하십시오. '-fno-common' 옵션. –

+0

@JonathanLeffler이 질문과 어떻게 중복 될 수 있습니까?제 질문은 gcc 컴파일러로 extern의 동작에 관한 것입니다. –

답변

3

이 코드는 진단 필요없이 정의되지 않은 동작입니다. 외부 링크 선언 식별자가를 sizeof 또는 _Alignof의 오퍼랜드의 일부 이외 (식에서 사용되는 경우

: Test1.cTest2.c 모두 C11 6.9/5 위배 외부 링크와 오브젝트 a 정의 연산자가 결과가 정수 인 경우), 전체 프로그램 의 어딘가에 식별자에 대한 하나의 외부 정의가 있어야합니다. 그렇지 않은 경우, 하나 이상은 존재하지 않는다.

참고 : "외부 정의"는 파일 범위의 정의를 의미합니다. (C11 6.9/4, 6.9/5). 다른 주석/대답은 "외부 정의"와 "외부 연결을 사용하는 객체의 정의"또는 "extern 키워드가있는 정의"를 혼동합니다. 파일 범위의 static int x = 5;은 외부 정의입니다.


Jonathan Leffler가 언급 한 바와 같이,이 특정 결과는 의도적 인 GCC 확장 일 수 있습니다. C11 Annex J.5.11에서 "Common extensions":

extern 키워드를 명시 적으로 사용하거나 사용하지 않고 개체의 식별자에 대한 둘 이상의 외부 정의가있을 수 있습니다. 정의가 일치하지 않거나 둘 이상이 초기화되면 동작은 정의되지 않습니다.

gcc가이 확장을 구현하면 관찰 한 동작을 설명합니다. 아마 "하나 이상이 초기화되었습니다"라는 견적은 임시 정의를 위해 생성 된 암시 적 초기화 프로그램을 계산하지 않습니다.