C 언어 두번째 정리 - 컴파일 과정
컴파일 과정
소스( .c) → 전처리 (.i) → 컴파일(.s) → 어셈블러(.o or .obj) → 링크/링킹 → 실행파일 (.exe)
※ 밑줄 부분은 컴파일 과정에서 중간 파일이 생겼다가 지워진다.
중간 파일을 삭제하지 않고 보여주는 방법.
# gcc -v [--save-temps] -o test2 first.c
-v → 컴파일 과정을 화면에 출력한다.
--save-temps → 컴파일 과정에서 생성되는 중간 파일인 전처리 파일(*.i)과 어셈블리 파일(*.s)를 지우지 않고 현재 디렉토리에 저장한다. 컴파일 과정의 에러를 분석할 때 사용.
출력화면
해당 디렉토리에 .i .s .o 의 파일과 실행파일이 생성되었다.
gcc 실행파일 생성 과정.
c 파일명을 abc.c 라고 가정하면 $gcc -o abc abc.c 를 실행해서 abc 라는 실행 파일을 만드는 과정은 아래와 같다.
(cc1(컴파일러) 과 collect2(링커) 가 존재하는 위치는 gcc 버전마다 조금씩 다르다.)
1. 전처리 (abc.i 파일 생성)
$cpp abc.c abc.i
2. 컴파일 (abc.s 어셈블러 파일 생성)
$/usr/lib/gcc/i486-linux-gnu/4.0.2/cc1 abc.i
3. 목적코드 생성( abc.o 오브젝트 파일 생성)
$as -V -Qy -o abc.o abc.s
4. 링킹 (ELF)
/usr/lib/gcc/i486-linux-gnu/4.0.2/collect2 --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o abc /usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../lib/crt1.o /usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../lib/crti.o /usr/lib/gcc/i486-linux-gnu/4.0.2/crtbegin.o -L/usr/lib/gcc/i486-linux-gnu/4.0.2 -L/usr/lib/gcc/i486-linux-gnu/4.0.2 -L/usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../lib -L/usr/lib/gcc/i486-linux-gnu/4.0.2/../../.. -L/lib/../lib -L/usr/lib/../lib abc.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i486-linux-gnu/4.0.2/crtend.o /usr/lib/gcc/i486-linux-gnu/4.0.2/../../../../lib/crtn.o
링킹은 조금 복잡하다. 여기서 -dynamic-linker 는 동적 링킹으로 라이브러리를 로드한다는 의미이며 crt 라고 붙은 오브젝트 파일은 리눅스 시스템에서 파일을 실행할때 초기화와 종료시에 실행되는 것들이 들어 있다. -L 옵션은 그 뒤에 있는 경로를 라이브러리 경로로 사용하겠다는 의미 -lxx 옵션은 libxx.x 라는 라이브러리를 읽어들이겠다는 의미가 된다.
기본 옵션
gcc -W -Wall -O2 -o test test.c
-Wall → 모든 모호한 코딩에 대해서 경고를 보내는 옵션
-W → 합법적이지만 모호한 코딩에 대해서 경고를 보내는 옵션
-W -Wall → 아주 사소한 모호성에 대해서도 경고
-O2 → 최적화 레벨을 2로 설정 (거의 대부분의 최적화를 시도)
o test → 컴파일된 파일명을 test로 하라는 의미
gcc 옵션
gcc -E test.c
-E → 전처리 과정의 결과를 화면에 보이는 옵션. 전처리 과정 중에 발생한 오류를 검증할 때 사용하면 좋다.
※ 더 강력한 옵션: --save-temps → 생성되는 test.i 파일을 읽어보는 것이 더 좋은 방법.
gcc -S test.c
-S → cc1으로 전처리된 파일을 어셈블리 파일로 컴파일까지만 수행하고 멈춘다. test.s 파일이 만들어진다.
gcc -c test.c
-c → as에 의한 어셈블까지만 수행하고 링크는 하지 않음. test.o 까지만 만들어진다.
gcc -v test.c
-v → 컴파일 과정을 화면에 출력한다.
--save-temps → 컴파일 과정에서 생성되는 중간 파일인 전처리 파일(*.i)과 어셈블리 파일(*.s)를 지우지 않고 현재 디렉토리에 저장한다. 컴파일 과정의 에러를 분석할 때 사용.
c 수업 두 번째
#include <stdio.h>
int main()
{
printf("1000\n");
printf("%x\n",1000);
printf("%o\n",1000);
printf("%x\n",1000);
return 0;
}
시그윈에서
gcc -o test1.exe main.c
./test1를 실행하면
숫자 1000을 입력하면 그대로 출력된다.
&d를 사용하면 10진수로 표시 - 1000
%o를 사용하면 8진수로 표시 - 1750으로 표시된다.
%x를 사용하면 16진수로 표시 - 3e8로 표시된다.
컴파일 과정 확인
소스(□.c) → 전처리(□.i) → 컴파일(□.s) → 어셈블리(□.o or .obj) → 실행파일(□.exe)
예제
첫 번째 빨간 사각형 안은 전처리 과정 중 에러가 발생한 것이다.
main.c:1:2 에서 1:2는 첫째줄과 둘째줄에서 에러가 발생했다는 뜻이고
invalid preprocessing directive #nclude 는 지시어가 명령한 #nclude가 전처리 과정중에 잘못되었다는 뜻이다.
directive는 컴퓨터 용어로 지시어(지시자)라는 뜻이 있다. 즉, 전처리기에 명령을 내린다.
두 번째 빨간 사각형 안은 컴파일 단계에서 에러가 발생한 것이다.
main.c:3: error: parse error before "main" 이라는 것은 main함수 앞에서 에러구문이 발생했다는 뜻.
세 번째 빨간 사각형 안 역시 컴파일 단계에서 에러가 발생했다.
main.c:3: error: parse erroe before ')' token 은 역시 main()에서 (이 빠져서 나온 에러가 표시된 것으로 token이란 기호에 의미가 부여되니 것들을 말한다 할 수 있다. 예를 들면 ;,(,{, 철수가, 집에, 등등 기호에 의미가 부여되어 있을 때 이것을 토큰이라 할 수 있다.)
※ 항상 에러의 해결은 에러 발생의 첫줄부터 시작한다. 첫 번째 에러로 인해 나머지 에러들이 발생한 것일 수가 있기 때문이다. 세 번째 빨간 사각형의 경우에서도 ‘(’를 빼먹었을 뿐이지만 뒤에 있는 모든 C 구문이 에러가 났다.
- 컴파일러 단계(Parser)에서 에러의 85% 이상이 발생한다.
- 나머지는 전처리 단계에서 10% 정도 링크/링킹 단계에서 5%정도의 에러가 발생.
참고 -토큰 (token)-
어휘(Token)
프로그램을 구성하고 있는 문법적으로 의미 있는 최소 단위
문장 “if (i<100) sum+=i;” 은 10개의 토큰으로 이루어짐
-> if, (, i, <, 100, ), sum, +=, i, ;
Mobile C 언어의 토큰
[참고]
gcc 컴파일 옵션(http://ssulsamo.egloos.com/5247105)
리눅스 gcc 실행파일 만들기 과정
(http://blog.naver.com/ohpowel?Redirect=Log&logNo=80024570104)
'내장형 하드웨어 > C언어' 카테고리의 다른 글
C 언어 네번째 정리 - 변수형, scanf, 상수, %(숫자)(형식연산자) (0) | 2011.03.28 |
---|---|
C 언어 세번째 정리 - 자료형(data type), printf, 메모리 크기 (0) | 2011.03.28 |
C 언어 - 변수형, scanf, 상수, %(숫자)(형식연산자), 마인드스톰(mindstorms) (0) | 2011.03.28 |
c언어 실습 (char, 대입연산자, printf) (0) | 2011.03.23 |
보수 정리 (0) | 2011.03.23 |