헤더파일
헤더파일은 모듈화(modular) 프로그래밍과 관련이 있다.

일반적으로 소프트웨어 공학에서 이야기하는 모듈(module)이라는 것은 크게는 하나의 파일이 될 수도 있지만, 작게는 하나의 함수가 될 수도 있다. 

구현하고자 하는 프로그램 코드를 기능별로 적절히 나눠서 독립된 파일에 저장하여 관리한다. 이렇게 관리되는 파일들을 모듈이라 한다. 그리고 이러한 방식으로 프로그래밍하는 것을 모듈화(modular) 프로그래밍이라 한다.

/* file.c */
#include <stdio.h>

int i = 0;

int main(void) 
{
    i++;
    printf("%d \n", i);
    return 0;
}


file.c 파일을 file_1.c와 file_2.c로 분리

/* file_1.c */
int i = 0;


/* file_2.c */
#include <stdio.h>

int main(void) 
{
    i++;
    printf("%d \n", i);
    return 0;
}
    


extern 키워드
파일을 나눌 경우 main 함수에서 참조하는 변수 또는 함수가 외부에(다른 파일) 선언되어 있음을 컴파일러에게 알려줘야 하는데 이러한 경우에 변수나 함수 앞에 붙는 키워드가 extern 이다. 함수 원형 선언에서 extern 키워드는 생략 가능하다. 

/* file_2.c */
#include <stdio.h>

extern int i;

int main(void) 
{
    i++;
    printf("%d \n", i);
    return 0;
}


static 키워드
전역변수 앞에 static 선언을 하면 외부의 접근을 금지한다는 뜻이 된다(정확히 표현하면 변수의 접근 영역을 파일로 제한한다는 뜻이다). 즉, 다른 파일에서 아무리 extern 선언을 해도 접근이 불가능한 전역변수가 된다.


링크(link)에 대한 이해
나눠진 파일을 컴파일하면 각각 오브젝트 파일이 생성이 된다. 이 오브젝트 파일은 단지 기계어로 변환된 내용만을 지닐 뿐이지 이 자체가 실행 가능한 상태는 아니다. 즉, "extern int i"라는 선언은 main 함수 내에서 접근하고 있는 변수 i가 외부에 존재한다는 정보만을 담고 있는 것이다. 정작 변수 i가 외부 어디에 존재하는지는 모른다.

따라서 main 함수에서 접근하고 있는 i와 이 i를 선언하고 있는 다른 오브젝트 파일의 전역변수 i를 연결 시켜 줄 필요가 있다. 그래야 하나의 완성된 실행 파일을 생성할 수 있기 때문이다. 이처럼 최종적인 실행 파일의 생성을 위해서 접근하는 변수가 어디에 존재하는지, 호출하는 함수가 어디에 존재하는지 연결해 주는 작업을 가리켜 링크라 한다.



표준 헤더 파일
ANSI-C에서 표준으로 정의하고 있는 함수를 사용하기 위해 포함시킨 헤더 파일을 말한다. 대표적인 예가 stdio.h 이다. 즉, ANSI 표준에서 정의하고 있는 헤더 파일이 표준 헤더 파일이다.

#include <stdio.h>         -> 표준 헤더 파일 포함
#include "file_1.h"          -> 사용자 정의 헤더 파일 포함



헤더 파일 생성
"extern int i" 처럼 main 함수에서 선언해야 하는 외부 변수가 수 없이 많다면, 그리고 main 함수가 아닌 다른 외부 파일에서도 사용한다면 상당히 번거롭게 될 것이다. 
따라서 우리는 이러한 번거로운 일들을 편히 하기 위해서 헤더 파일이라는 것을 만든다.

/* file_1.c */
int i = 0;

/* file_1.h */
extern int i;

/* file_2.c */
#include <stdio.h>
#include "file_1.h"

int main(void) 
{
    i++;
    printf("%d \n", i);
    return 0;
}



출처 - 열혈강의 C 프로그래밍






1. 라이브러리와 헤더는 엄연히 다릅니다. 라이브러리는 기계어로 번역된 바이너리이며, 헤더는 컴파일러가 컴파일하기전.. 그러니까 프로그래머가 알아먹을 수 있고 c/c++의 문법에 맞게 작성되어있는 선언들의 집합입니다.

라이브러리를 사용하기 위해서는 해당 라이브러리의 헤더파일이 있어야합니다. 그래야지만 링커가 알아먹을수 있는 심볼네임을 컴파일러가 만들어내기 때문입니다.

컴파일러가 이런 헤더파일을 가지고 심볼네임을 만들어서 오브젝트 파일에 넣어주면 링커가 해당 심볼네임을 가지고 라이브러리를 뒤져서 링크를 하게 됩니다.

헤더가 여러개 모이는게 라이브러리가 아닙니다. 라이브러리는 컴파일된 바이너리이므로 소스파일의 컴파일된 산물인 오브젝트(리눅스의 경우에는 .o , 윈도우의 경우에는 .obj)파일을 여러개 모아놓은게 라이브러리입니다.

라이브러리의 확장자는 리눅스의 경우에는 .a, 윈도우의 경우에는 .lib입니다.

2. 제가 리눅스를 많이 안써봐서 말씀하신 위치 이외에 라이브러리와 헤더가 들어가는지는 모르겠습니다. (물론 나열하신 위치 말고도 다른 위치를 컴파일러 옵션으로 지정이 가능합니다.)
다만 나열하신 위치에 들어있는 파일들이 라이브러리와 헤더들입니다..

3. visual c보다는 visual c++이라고 하셔야 맞을거 같습니다.. 물론 6.0, .net 2003 .net 2003, .net2005과 같이 여러버전이 존재합니다.

4. 일반적으로 표준 c라이브러리는 대부분의 c컴파일러가 지원합니다. 표준 함수를 알고 계시면 대부분의 컴파일러에서 동일하게 소스를 바꾸지 않고 컴파일이 가능합니다.

5. 컴파일러와 라이브러리는 별개입니다. 컴파일러를 설치하면 들어있는 표준 c라이브러리도 사실 없어도 프로그램이 컴파일되는데는 문제가 없습니다. 대신 직접 모든걸 다 해줘야하는게 문제입니다. c언어의 시작 함수가 main이지만 실제로는 이 main함수를 호출하기전에 해주는 것이 많습니다. 그런걸 직접 일일이 만들어줘야하는 것이죠..

그리고 라이브러리는 c표준 라이브러리 뿐만 아니라 누구든지 라이브러리로 구성하면 그게 다 라이브러리입니다.


출처 -  http://kldp.org/node/84138 




11. 라이브러리와 헤더파일


원시 프로그램은 여러 파일로 나누어 각각 별도로 번역할 수 있는데 번역(compile)된 루틴들을 모아둔 파일을 라이브러리(library)라 한다. 프로그램에서 라이브러리 루틴을 사용하려면, 마치 함수가 사용자 프로그램에 정의되어 있는 것처럼 간단히 호출만 하면 된다. 라이브러리 함수는 번역된 형식으로 저장되어 있기 때문에 사용자 프로그램은 라이브러리 파일 또는 라이브러리 함수를 포함하는 파일과 링크(link)되어야 한다. 라이브러리를 다른 파일과 링크하면, 선언된 라이브러리 함수만이 실행파일에 포함되지만, 파일에 함수를 작성해 두고 번역하여 두 파일을 링크시키면, 불필요한 함수까지 코드로 첨가되기 때문에 라이브러리는 디스크 공간과 주 메모리를 절약하는데 필요하다.

main()함수에서 외부함수는 사용되기 전에 선언되어야 하기 때문에 만약 외부함수가 많거나 여러번 사용되려면, 사용 전에 매번 선언되어야 하고 선언이 정확해야 하기 때문에 번거러운 문제가 야기된다. 따라서 함수에 대한 선언을 외부파일에 하나로 통합시켜 두고 원시프로그램에 포함시키기 위하여 작성된 파일을 헤더파일(header file)이라 한다. 라이브러리의 대다수 루틴들은 함수정의 및 선언들을 필요로 하기 때문에 링크되기 전에 선처리기에 의하여 해당 헤더파일을 원시프로그램에 포함시켜야 한다.

   C의 실행시간 라이브러리에 있는 대부분의 루틴들은 함수이나, 어떤 루틴은 매크로로 구현되어 있다. 매크로는 기능상 함수와 같으나 문자열들은 프리프로세스 단계에서 코드로 치환하기 때문에 함수 호출시의 비용을 줄일 수 있고, 실행시간이 함수보다 빠르다. 그러나 매크로가 반복해서 호출될 경우에는 코드의 반복된 치환으로 인하여 프로그램의 크기가 확장되는 단점을 갖기도 한다.

 

■ 매크로와 함수의 근본적인 차이점

   1)  매크로의 매개변수를 여러 번 평가하면 부작용으로 잘못 평가될 수 있다.

   2)  매크로명은 함수처럼 주소에 의하여 평가되지 않기 때문에 사용자가 포인터를 요구하는 경우에는 매크로를 사용할 수 없다. 만약 사용자가 함수호출시에 매개변수로 매크로명을 사용하면 매크로에 의하여 계산된 값이 전달된다.

   3)  매크로는 함수가 아니기 때문에 선언될 수 없고, 매크로를 포인터로 참조할 수 없다. 그리고 매크로의 매개변수에 대해 자료형 검사가 없다. 그러나 인수의 갯수는 검사된다.

   4)  매크로로 정의된 라이브러리 루틴은 라이브러리의 헤더파일에 #define으로 정의된다. 따라서 라이브러리에 정의된 매크로를 사용하려면 사용자는 해당 헤더파일을 포함시켜야 한다.

 

■ 헤더파일에 서술된 내용

   다수의 실행시간 루틴은 별도로 매크로와 상수, 변수 그리고 자료형을 사용하기 때문에 번역될 프로그램 파일에 이들을 연결해야 한다. 헤더파일의 내용은 실행시간 루틴에 따라 다르나, 일반적으로 다음과 같은 내용들을 정의해 두고 있다.

   1) 헤더파일은 특정한 변수나 분명한 상수를 정의한다. 예를 들면 입출력에 필요한 버퍼의 크기 등 실행동안에 불변하는 자료를 정의해 둔다.

   2) 헤더파일은 특정한 자료형 내지 자료구조를 정의한다. 실행루틴이 매개변수나, 구조적 자료형을 반환값으로 갖는 경우에 이러한 자료형을 정의해 둔다. 예를 들면 스트림 입출력 연산자는 FILE형에 대한 포인터를 사용한다.

   3) 헤더파일은 함수의 정형이나 다른 언어의 함수를 실행시간 루틴에 사용할 때 이들을 사용자 프로그램에 포함시키고 라이브러리 루틴과 연결하기 위하여 선언된다.

   4) 헤더파일은 매크로를 정의한다.

   5) 헤더파일은 Directives를 사용한다.

       - #include

       - #define TRUE -1

       - #undef argument : argument의 정의를 취소한다.

       - #if - #else -

              #elif -

              #endif

       - #error <메시지> : 컴파일을 중단하고 <메시지>를 보여준다.

       - #line <number> <file>: 파일 <file>의 행번호 <number>로 점프

       - #if defined(<arg_1>)  #else : <arg_1>이 정의되어 있으면 뒷 부분을

               컴파일하고, 그렇지 않으면 #else 부분을 번역한다.

       - #if !defined(<arg_1>) else : <arg_1>이 정의되어 있지 않으면 뒷부분

               을 컴파일하고, 그렇지 않으면 #else 부분을 번역한다.

 

       ☞   #if defined(_header2)

   #error HEADER1.H and HEADER2.H cannot be used simultaneously.

   #else

   #define _header1

   #if defined(PI)

   #endif

   #define PI 3.14159

   #endif

 

   Directive로 서술된 내용을 사용자 프로그램에 포함시키려면, 그에 대한 헤더파일을 #include로 선언해야 한다. 

   ☞    #include <function.h>

main()

{    int  i, j, k;

}

 

/* function.c 원시 파일 */

int  increment(int a)

{     return (a+1);

}

 

/* 헤더파일 function.h */

int  increment(int);

 

■ 헤더파일의 종류

   헤더파일은 C 시스템의 서브 디렉토리인 INCLUDE에 있는데 헤더파일의 선언내용은 컴파일러마다 다를 수 있으나 일반적으로 아래와 같은 내용을 포함하고 있다.

 

   1)  <conio.h> : 입출력 포트와 콘졸(console)에 대한 모든 함수를 선언하고 있다.

   2)  <ctype.h> : 문자부류에 사용된 전역변수를 선언하고, 이에 대한 상수와 매크로를 정의한다. 예를 들면 islower(), toascii(), _tolower()와 같은 매크로와 _upper, _lower와 같은 상수를 정의하고, _ctype과 같은 전역변수를 선언한다.

   3)  <direct.h>:  chdir, getcwd, mkdir와 rmdir와 같이 디렉토리를 제어하는 함수를 포함하고 있다.

   4)  <dos.h> :  int86, int86x, intdos와 같이 MS-DOS 인터페이스 함수에 대한 매크로 정의, 함수선언, 형 정의를 포함하고 있다.

   5)  <errno.h> :  errno 변수의 값을 정하기 위하여 시스템 수준의 호출에서 사용되는 값을 정의한다.

   6)  <fcntl.h> :  파일이 텍스트모드 또는 이진모드로 해석되는지를 제어하고, 파일이 열리는 연산자의 형을 서술하기 위하여 호출되는 open과 fopen에서 사용되는 프래그(flag)를 정의한다.

   7)  <io.h> :  eof, open, tell, read, lseek, tell과 같이 저수준 입출력 함수와 파일처리에 필요한 함수를 선언하고 있다.

   8)  <malloc.h>: calloc, malloc, realloc과 같이 동적으로 메모리를 할당하는 함수를 선언하고 있다.

   9)  <math.h> : sqrt, sin, log10, pow, matherr와 같은 모든 수학루틴에 대한 함수를 선언하고 있다.

   10) <memory.h>: memcpy, memcmp, memset와 같이 버퍼 변경루틴에 대한 함수를 선언하고 있다.

   11) <process.h>: abort, exit, execle, system과 같이 모든 프로세스 제어함수를 선언하고 있다.

   12) <search.h> : bsearch, qsort와 같은 함수를 선언하고 있다.

   13) <signal.h> : signal과 같이 신호에 대한 값을 정의하고 있다.

   14) <stdio.h>  : fclose, fopen, gets, fread, scanf, printf, fprintf, fscanf와 같이 스트림 입출력에 대한 함수선언 및 매크로와  FILE과 같은 자료형과, EOF, NULL, BUFSIZ와 같은 상수를 정의하고 있다.

   15) <stdlib.h> : abs, atoi, itoa, rand, toupper, getenv와 같은 함수선언을 포함하고, errno와 같은 전역변수 선언하고 있다.

   16) <string.h> : strcat, strcpy, strcmp, strncmp와 같이 문자열 처리함수를 포함하고 있다.

 

   이밖에 운영 시스템과 C 언어의 유형에 따라서 여러 헤더파일이 있으며, SYS라는 서브 디렉토리에는 시스템 수준의 호출에 사용되는 함수, 매크로, 변수 및 상수들이 선언 또는 정의되어 있다.


출처 - http://stbiho.daegu.ac.kr/~minmild/c-lang/11.htm






'Development > C' 카테고리의 다른 글

c - 전처리문의 종류  (0) 2012.10.28
gcc 옵션 정리 - 자바 -D 옵션 의미  (0) 2012.03.23
헤더파일과 라이브러리  (0) 2012.02.24
C에서 정의된 FILE 구조체  (0) 2012.02.22
C 표준 라이브러리  (0) 2012.02.11
C언어 표준  (1) 2012.02.11
Posted by linuxism

댓글을 달아 주세요