선언과 호출 순서, 영역
함수와 변수 선언의 위치에 따라 호출 할 수 있는 영역이 결정된다.
a = 10; // 컴파일 에러 (지정되지 않은 변수명 a)
int a;
위와 같이 값을 선언하는 부분과 참조하는 부분의 순서가 뒤바뀌면 컴파일 에러가 발생한다.
함수나 변수를 선언할 때는 용도에 따라 아래와 같이 세 영역 중 어디에 선언할지 선택을 해야 한다.
- 프로젝트 전체에서 참조 (global)
- 현재 파일에서만 참조 (static)
- 특정 영역에서만 참조
영역
프로젝트 전체(global) 영역은 다른 소스 파일을 넘나 들며 공유되는 공간이다.소스 파일 내 영역은 해당 변수가 선언되는 파일 내에서만 공유되는 공간이다.
특정 영역은 { } 로 감싸진 영역 내만 공유되는 공간이다.
C 프로젝트
프로그램이 하는 기능이 많아 질수록 코드는 늘어난다.소스 파일 하나에 많은 코드를 넣으면 구분하기가 힘들어진다.
그래서 보통 관련도에 따라 소스 코드를 여러 파일로 분산 시킨다.
예제 프로젝트
- util.h
- util.c
- main.c
util.h
#ifndef __UTIL_H__
#define __UTIL_H__
extern void hello(void);
#endif
util.c
#include <stdio.h> #include "util.h"
void hello(void) {
printf("Hello\n");
}
main.c
#include "util.h"
int main(int argc, char * args[]) {
hello();
return 0;
}
컴파일:
$ gcc -o hello util.c main.c
실행:
./hello
Hello
헤더 파일 include
소스 파일 간 공유하고 싶은 변수나 함수 등이 있는 경우 헤더 파일에 변수 선언 또는 함수 선언문을 작성한다.헤더 파일은 .h 확장자로 저장한다.
#include 문으로 헤더 파일을 참조할 수 있다.
#include "" 와 #include <> 탐색 순서 차이
- #include "" 는 같은 위치의 header 파일을 먼저 탐색
- #include <> 는 컴파일러에 -I 옵션에 지정한 경로를 먼저 탐색
위 예제에서 util.h 는 자신이 만든 헤더 파일이고 같은 경로에 위치 시켰으므로 "" 로 감싸 #include "util.h" 로 작성하였다.
stdio.h 는 표준 라이브러리로 아직 어디인지는 살펴보지 않았지만 현재 자신의 프로젝트 밖에 존재하므로 #include <stdio.h> 로 작성하였다.
헤더 중복 방지 처리
컴파일러는 같은 헤더 파일이 여러 번 참조되는지 검사하지 않고 #include 문을 만나면 무조건 읽어 들인다.
함수 선언문이나 변수 선언문이 중복되면 컴파일 에러가 발생한다.
이를 방지하기 위해 아래와 같이 전처리기를 사용한다.
#ifndef __UTIL_H__
#define __UTIL_H__
...
#endif
#ifndef ~ #endif 문
#ifndef 는 값이 define 되어 있는지 검사하여 define 되어 있지 않다면 #endif 문까지 진행한다.
아니면 #endif 문 다음으로 진행한다.
if not defined 의 줄임말
#ifndef __UTIL_H__ // __UTIL_H__ 가 아직 define 되지 않았으면 이 헤더 파일은 처음으로 읽힘
#define __UTIL_H__ // __UTIL_H__ 를 define 하여 다음 번 #ifndef __UTIL_H__ 검사에서 제외되도록 처리
extern void hello(); // 이 코드는 한번만 수행됨
#endif // #ifndef 문 끝
중복되지 않는 define 값
주의할 점은 define 값은 다른 파일과 중복이 되지 않도록 지정해야 한다.
이름을 짓는 일은 나름 스트레스 이기 때문에 보통 자신만의 규칙을 정하기도 한다.
일반적으로 파일명 변형하는 방법을 사용한다.
util.h -> __UTIL_H__ 또는 __UTIL_H
미리 자신만의 방식을 정해두는 게 좋다.
프로젝트 전체에서 참조 (global)
선언부와 구현부가 다른 파일들로 나뉜다.선언부는 헤더 파일에 구현부는 소스 파일에 작성한다.
위 예제를 보면 선언문은 util.h 파일에 있고 구현부는 util.c 파일에 존재한다.
extern 함수 선언문:
extern void hello();
extern 함수 구현문:
void hello() {
printf("Hello");
}
extern 은 컴파일러에게 해당 함수나 변수가 구현부 외 다른 소스 파일에서도 참조될 수 있게 global 영역에 변수를 선언하라는 의미이다.
extern 변수 선언문: 헤더 파일
extern int global_value;
extern 변수 선언문: 소스 파일
int global_value;
extern 변수는 소스 파일에 extern 을 제외한 선언문을 한번 더 써 줘야 한다.
현재 파일 내에서만 참조 (static)
소스 파일 내에서 선언: 다른 소스 파일에서 참조할 수 없음static int a;
현재 영역에서만 참조
{int a;
}
복합 예제
util.h
#ifndef __UTIL_H__
#define __UTIL_H__
extern int global_number; // global variable
extern void global_hello(); // global function
#endif
util.c
#include <stdio.h>
#include "util.h"
int global_number = 0;
void global_hello() {
printf("Global Hello\n");
}
main.c
#include <stdio.h>
#include "util.h"
static int static_number;
static void static_hello();
void static_hello() {
printf("Static Hello\n");
printf("Static Number: %d\n", static_number);
}
int main(int argc, char * args[]) {
printf("Global Number: %d\n", global_number);
global_hello(); // global function
static_hello(); // static function
{
int local_number = 100;
printf("Local Number: %d\n", local_number);
}
// local_number 는 여기서 사용할 수 없음
}
댓글 없음:
댓글 쓰기