반응형

C : extern 키워드

작성계기

실제로 실수를 했었고, 찾아보니 의외로 다른사람도 잦은 실수를 하는 것 같아서 작성함.


키워드의 의미

다른 파일에 있는 변수를 현재 파일에서 사용하기 위해서 사용하는 키워드이다. 원리상 다른 파일 어딘가(메모리의 어딘가)에 해당변수가 있으니 그걸 참조하라는 의미가 된다.


예시)

a.c (변수가 정의 되어 있는 파일)

int a = 0;


b.c (a.c 파일에 있는 변수를 호출해서 사용하는 파일)

extern int a;
a = 20;


활용 및 응용

매번 새로운 파일에서 참조를 할 때마다 앞단에 extern 키워드로 사용가능하게 하는 것은 상당히 번거롭기 때문에 해당되는 헤더파일에 작성하여 여러번 작성을 하지 않게 할 수 있다.


예시)

a.c (변수가 정의 되어 있는 파일)

#include "a.h"
int a = 0;


a.h (변수가 정의 되어 있는 파일의 헤더파일)

#pragma once
extern int a;


b.c (a.c 파일에 있는 변수를 사용하는 파일)

#include "a.h"
a = 20;


당연한 말이지만, 해당 선언을 중복으로 선언하게 되면, 오류가 된다. 따라서 #pragma once 혹은 #ifndef를 활용하여 중복선언을 피하도록 하자.


실수하는 예

C의 전형적인 함정은 주로 배열에서 발생된다. 배열로 선언/정의 한것과 포인터로 선언/정의 된것은 다른 것으로 컴파일러가 구분한다. 의미상 배열선언의 키워드도 포인터로 같은 종류로 (사람은) 인식하지만, 컴파일러는 다른 것으로 인식을 한다.


예시)

a.c (정의된 원본 파일)

char a[] = "abc";


b1.c (오류/에러로 인식 "그런거 없다고 한다")

extern *a;
char b = a[0];


b2.c (정상 호출)

extern a[];
char b = a[0];



반응형
반응형

리눅스/윈도우 C : 헤더파일 중복 참조 방지

알게된 배경

 참여하는 프로젝트에서 소켓 네트워크 프로그램을 만들어야 하는데, 가장 먼저 잡은 책이 하필 C로 실습하는 책이었다. 문제는 C는 운영체제를 많이 타는 편이라서 리눅스와 윈도우를 같이 번갈아가면서 사용해야 했다.


들어가기에 앞서

 현재 C도 C++처럼 표준이 존재하며, 리눅스는 C90 ~ C99를 지원하고, 윈도우는 C80만 지원한다. 따라서 지속적으로 계속 차이가 날 수 밖에 없다. 그리고 대부분의 C 학습 서적은 대부분 윈도우 환경의 Microsoft Visual(MV) C++ 컴파일러를 기준으로 되어 있다.


매크로변수로 구분하는 방법(#ifndef)

예시)

#ifndef _HEADER_H_
#define _HEADER_H_

int func1(void);

#endif //_HEADER_H_

초기 C에서 사용되는 방법으로 매크로 변수 선언여부에 따라서 컴파일러는 정해진 구간의 코드를 컴파일하지 않는다. 매크로는 컴파일 하기전에 실행되는 것이기 때문에 이를 통해서 매번 다른 C파일에서 중복으로 헤더파일을 인클루드 해도 컴파일러는 여러번 참조하지 않는다. 헤더파일 중복 참조를 막기 위한 변수명은 위의 코드처럼 _(언더바)로 시작하고 대문자로 작성하며, 마지막에 _H_로 표기하도록 권장한다.


 다만, 기기 입장에서 컴파일을 할때 매크로에 의해서 컴파일전에 헤더파일의 내용을 건너뛰기는 하지만, 파일 전체가 아닌 구간을 넘기는 거라서 원리상 파일을 중복 참조하기는 한다. 그렇지만, 이게 워낙 빨라서 사람이 체감하기는 어렵다.


한번만 읽는 매크로를 실행하는 방법(#pragma once)

#pragma once

int func1(void);

MV C++ 에서 사용하기 시작한 방법이다. 매크로는 컴파일러가 컴파일전에 작업한다는 것을 다시 한번 상기하자. 매크로 명령어로 컴파일러에게 컴파일전에 이 파일은 한번만 읽으라고 하는 의미이다. 결국 앞의 매크로변수 유무에 따라서 컴파일하는 것과 같은 결과를 갖게 되는데, 원리상 차이가 있다.


 파일을 한번만 읽으라고 했기 때문에 아무래도 매크로 변수 존재 유무를 확인하고 구간을 건너뛰는 것보다는 매크로실행과정이 짧아진다. 물론 속도 차이는 체감이 거의 안된다.


중복참조 선택방법

 이러한 매크로(#pragma once)는 처음에 MV C++에서만 지원이 되었고 비표준이었다. 하지만, 요즘에는 표준화가 되었다. 그러나 아직 표준화 된지 오래 안되어서 인지 지원이 안되는 컴파일러가 있을 수 있기에 아직도 매크로 변수를 이용한 중복 참조를 피하는 방법을 리눅스 프로그래밍(OS X 에서도) 쪽에서는 아직도 많이 사용하고 있다.


 자신의 개발환경이 오래된 혹은 가벼운 컴파일러를 사용해야 할 경우에는 어쩔 수 없이 매크로변수를 이용해야 하고 그게 아니라면 #pragma once를 사용하자.


위키피디아에서 #pragma once 매크로가 지원되는 컴파일러 목록이 정리되어 있다

[참조링크]


반응형

+ Recent posts