리눅스에서 C 프로그래밍 개발 환경 구축
GCC
- GNU 프로젝트의 오픈 소스 컴파일러 집합
- 1987, 리처드 스톨먼
- GNU C Compiler의 약어로 시작
- GNU Compiler Collection으로 변경: C(gcc), C++(g++), Objective-C(gobjc), D(gdc), Go(gccgo), Ada(gnat), Fortran(gfortran) 지원
- 유닉스/리눅스 계열의 사실상 표준 컴파일러
- Windows, BSDs 및 기타 OS에서도 사용 가능
- 통합개발환경이라기보다는 명령행 모드에서 실행
- vi로 작성 → gcc로 컴파일 → make로 빌드
개발환경 구축
1단계: 시스템 업데이트
- 충돌 발생하지 않도록 모든 관련 패키지 업데이트
$ sudo apt update- sudo : 명령어 실행시 관리자 권한을 부여받기 위해
- apt : 우분투(데비안 계열)의 SW 패키지 관리 프로그램 (advanced packaging tool)
- update (apt 명령어의 옵션)
2단계: build essential 패키지 설치
- GCC 패키지와 다른 응용 패키지로 구성
$ sudo apt install build-essential- install: apt 명령어의 옵션
- build-essential : 설치할 패키지명
3단계: 설치 확인
- 성공적인 설치를 위해 c 컴파일러 버전 확인
$gcc --version
하나의 소스파일로 구성된 C 프로그램의 작성
C 프로그램의 기본 작성
- vi 에디터로 소스 코드 작성
$ vi helloworld.c
- 컴파일하고 링크하기
$ gcc [-o <생성할 실행파일 명>] <소스파일명.c>:-o옵션 생략시a.out이라는 이름으로 실행파일이 생성됨$ gcc -o helloworld helloworld.c
- 실행하기
$ ./helloworld
다수의 소스 파일로 구성된 C 프로그램의 작성
컴파일/링크 과정

다수의 소스 파일로 구성된 예

인터페이스의 내용
- Function prototype(함수 원형): 함수의 몸체({...}) 없이, 이름-입력값(매개변수)-출력값(반환형)만 선언한 것 (e.
int add(int a, int b);) - Constant definition(상수 정의) (
#define): 프로그램 전체에서 공통으로 사용할 변하지 않는 값 (e.#define MAX_BUFFER 1024) - Type definition(타입 정의) (
typedef/struct) : 구조체 등을 사용하여 새로운 자료형을 만드는 것 (e. typedef struct { int x; int y;} Point;)
인터페이스(Interface) in C언어?
: .h(헤더 파일) 형태로 존재. 내가 짠 코드를 남이(또는 다른 파일이) 어떻게 써야 하는지 알려주는 공적인 약속
인터페이스 파일의 형식
: 하나의 인터페이스가 다양한 경로를 통해 여러 번 내포되더라도 컴파일러가 매번 다시 읽어들이지 않도록 하기 위해
#ifndef _headerFileName_h
#define _headerFileName_h
any required #include lines
interface entries
#endif
#ifndef _headerFileName_h: "If Not Defined"의 약자. 이 파일이 처음 로드되었는지 확인하는 관문. 만약 이미 한 번 로드되었다면(이미 정의되어 있다면), 바로#endif로 점프해서 파일 내용을 무시한다.#define _headerFileName_h: 지금부터 _headerFileName_h라는 이름표를 정의(Define)any required #include lines: 이 인터페이스 파일이 제대로 작동하기 위해 필요한 다른 헤더 파일들을 가져온다.- i
nterface entreis: 인터페이스의 3요소가 여기에 들어감. 실제 사용자에게 제공할 기능들을 나열하는 곳 #endif: #ifndef로 시작된 조건문(if)이 여기서 끝남
프로그램의 단계별 작성
: 한 프로그램이 여러 개의 소스 파일로 나뉘어 구성되어 있는 경우 좀 더 효율적으로 작성하기 위해
1. 컴파일하기 $ gcc -c <소스파일명.c> : 소스파일명.o의 이름으로 오브젝트 파일 생성
2. 링크하기 $ gcc [-o <실행파일명>] <오브젝트파일명.o> : -o 옵션 생략시 a.out 이라는 이름으로 실행파일이 생성
단계별 작성
: 한 프로그램이 여러 개의 소스 파일로 나누어 구성되어 있는 경우
- 특정 소스 코드가 수정된 경우 → 전체를 컴파일하지 않고서도 개발할 수 있어야 함
- 각 소스파일이나 오브젝트 파일의 의존관계에 따라 필요한 파일만 재 컴파일하는 것이 필요
실습 예시
~$ mkdir multi
~$ cd multi
~/multi$ vi main.c
#include <stdio.h>
#include "simpio.h"
int main(void)
{
int grade;
printf("학년을 입력하시오: ");
grade = GetInteger();
printf("당신의 학년은 %d학년입니다.\n", grade);
return 0;
}
:wq
~/multi$ vi simpio.h
#ifndef _SIMP_IO_H_
#define _SIMP_IO_H_
int GetInteger(void);
#endif
~/multi$ vi simpio.c
#include "simpio.h"
#include <stdio.h>
int GetInteger(void)
{
int n;
scanf("%d", &n);
return n;
}
:wq
~/multi$ ls
main.c simpio.c simpio.h
~/multi$ gcc -o myprog main.c simpio.c
~/multi$ ls
main.c myprog simpio.c simpio.h
~/multi$ ./myprog
학년을 입력하시오: 3
당신의 학년은 3학년입니다.
~/multi$
자동 빌드 도구 make와 Makefile
make 유틸리티
: 프로그램 그룹을 유지하는데 필요한 유틸리티. 다수의 소스파일로 구성된 프로젝트에서 의존 관계에 따라 좀 더 효율적으로 개발하기 위해 사용
- build essential 패키지 내에 포함
- $ make [-f <메이크파일>]

Makefile
: make 명령 사용시 참조되는 파일
- 실행 파일을 만들기 위해 필요한 파일들 간의 상호 의존 관계 및 생성 방법 등을 기술
- 어떤 이름도 가능하나 관례적으로 Makefile 혹은 makefile로 기술
Makefile의 구성 형식
target: dependencies commands
- 목표(target) or 레이블(label)
- 생성하고자 하는 목표(오브젝트 파일명이나 실행 파일명)
- 명령이 수행되어 나온 결과 파일 (또는 동작에 대한 레이블)
- 의존 관계 목록(dependencies) : 목표 생성시 필요한 파일명들
- 명령 목록(commands)
- 의존관계에 기술된 파일 변경시 목표 생성을 위한 명령어
- 행의 시작이 탭 문자로 시작해야 함
Makefile의 작성 예
myprog: main.o simpio.o
gcc -o myprog main.o simpio.o
main.o: simpio.h main.c
gcc -c main.c
simpio.o: simpio.h simpio.c
gcc -c simpio.c

- Makefile 이용 방법: $ make
Makefile 작성시 매크로 사용
: 특정한 표현을 간단하게 기술하기 위해 사용. 사용되기 전에 먼저 정의되어야 함!
OBJECTS = main.o simpio.o
myprog: $(OBJECTS)
gcc -o myprog $(OBJECTS)
main.o: simpio.h main.c
gcc -c main.c
simpio.o: simpio.h simpio.c
gcc -c simpio.c
Makefile 작성시 레이블 사용
- 사용 방법: $ make clean
OBJECTS = main.o simpio.o
myprog: $(OBJECTS)
gcc -o myprog $(OBJECTS)
main.o: simpio.h main.c
gcc -c main.c
simpio.o: simpio.h simpio.c
gcc -c simpio.c
clean:
rm myprog $(OBJECTS)