2013-06-14 5 views
1

내가 file.h이 있다고 가정하고 그 안에 내가 가진 :왜 .h 파일의 변수를 선언하면 각 .c 파일에 대한 메모리가 할당됩니다. ANSI C입니까?

int arr[128]; 
(void)(*func_ptr)(int); 

을 그리고 code1.c, code2.c는, code3.c가 포함되어 있습니다. arrfunc_ptr은 각 .c 파일에 대해 전역 범위로 할당됩니까? 즉 각 .c 파일의 인스턴스가 arr이고 func_ptr일까요? 그렇다면 왜 그렇습니까?

을 사용하면 static의 결과가 바뀔 수 있습니까? ANSI c 규칙은 무엇입니까?

+0

질문에 대한 모든 downvotes가 대답하고 대답하는 이유 ???? – 0x90

+0

나는 이것에 대해서도 궁금해했다. 때로는 사람들이 재미있게 downvoting하는 인상을 가지고 있습니다. :(정적 대답을 포함하도록 답변을 업데이트했습니다. – Devolus

답변

2

arr 및 func_ptr은 각 .c 파일에 대해 전역 범위가 할당됩니까?

예, 전역 변수에서 동일한 변수 이름을 여러 곳 정의했기 때문에 연결 오류가 발생합니다.

.c 파일에 #include하는 헤더 파일은 .c 파일에 방금 삽입됩니다. 특별한 내용은 없습니다. .c 파일에 포함 된 모든 헤더 파일을 연결 한 다음 결과를 컴파일하는 것처럼 작동합니다. 그런 점에서

는 최종 결과는 명시 적으로 C 전문 용어에서 "임시 정의을"이라고 변수를 초기화하지 않고 .c 파일이 같은

+0

왜 아래로 투표 ?? – 0x90

+0

멋지다. 그래서'static int arr [128]'을 넣어야하고 각 파일은 자신의'arr'을 가질 것이다. – 0x90

1

변수 arr이 전역 범위이므로 중복 심볼이있는 링커 오류가 발생하므로 컴파일되지 않습니다.

정적으로 선언하면 별도의 메모리가있는 각 소스 파일에 할당되지만 해당 소스 파일이나 포인터를 통해 명시 적으로 다른 파일에 액세스 할 수 있습니다.

각 소스 파일에서 동일한 메모리 블록에 액세스하려는 경우 위의 파일 하나와 다른 파일의 앞에 extern이 추가되어야합니다. 당신이 그것을 정의 어디서나 정의에 static를 추가하는 경우

같은이 func_ptr

업데이트

입니다, 그 범위는 지역이다. 전역 정적 변수를 정의하면 해당 모듈에서만 볼 수 있습니다. 함수에서 정적 변수를 정의하면 해당 함수에서만 정적 변수가 표시되므로 간섭없이 여러 함수에서 동일한 이름을 사용할 수 있습니다.

foo1() 
{ 
    static int i; 
} 

foo2() 
{ 
    static int i; 
} 

네임 스페이스와 비슷하게 동작하므로 잘 컴파일됩니다.

+0

OP가 헤더 파일에서 선언하고 한 번만 정의하면 괜찮습니까? 그냥 같은 소스 파일을 포함하여 여러 소스 파일을 사용해 보았습니다. 머리글하지만 함수를 정의한 함수 하나를'main'에서 호출했을 때 잘 동작했습니다 (물론 다른 사람이 헤더를 사용하여 사용하지 않을 것입니다). – Nobilis

+0

함수 정의가 복사되지 않습니다. !! 변수와 포인터 만 복사됩니다. –

+0

include 파일에서 선언하고 여러 소스 파일에 포함하면 선언문이 모든 파일에 포함되므로 'extern' 키워드를 사용해야합니다. 차이점이 있는지 확인하기 위해 코드를 살펴 봐야합니다.이 코드는 컴파일 될지라도 반드시 링크되지 않아야합니다. 위의 샘플은 선언이 아닌 함수의 변수입니다. – Devolus

4

선언의 각 int arr[128];을 썼다 정확히 것처럼입니다. 문제없이 여러 컴파일 단위에서 사용할 수 있습니다.기호 효과적으로 당신이 단위의 한에서 (초기화 포함) 하나의 실제 정의가 있어야 구현되는 적어도 하나 개의 컴파일 단위,

int arr[128] = { 0 }; 
(void)(*func_ptr)(int) = 0; 

편집 같은이 있는지 확인하려면 관련을

이니셜 라이저없이 범위 파일이있는 오브젝트의 식별자의 선언 및 스토리지 클래스 지정자없이 또는 스토리지 기반으로 다음 C 표준의 일부는 다음의 6.9.2에서 파라이고 정적 인 클래스 지정자, 임시 번호을 구성합니다.정의. 번역 단위에 식별자에 대한 정의가 하나 이상 포함되어 있고 번역 단위에 해당 식별자에 대해 외부 정의가 포함되어 있지 않은 경우 번역 단위에 식별자의 파일 범위 선언이 포함 된 것처럼 정확하게 인 것처럼 동작합니다. 0이 같은 이니셜 라이저가있는 단위의 변환이 끝날 때의 복합 유형

+0

필자는 이것을 gcc를 사용하여 샘플로 테스트 한 결과 링크 할 때 중복 심볼 오류가 예상대로 발생했습니다. 그래서 당신이나 gcc가 잘못되었습니다. 아니면 C++로 컴파일 할 때 C와는 다른 점이 있습니까? – Devolus

+0

흠, 괴상한 답변을하기 전에 테스트 해 보았습니다. gcc는 'Wallpedantic'을 사용하는 경우에도 문제없이 이것을 허용합니다. –

+0

값없이 'int global;'을 선언했고 결과는'(.bss + 0x0) :'_global''의 다중 정의 – Devolus