[임베디드 C] 컴파일 내부동작

정재훈·2022년 4월 4일
0

임베디드 C언어

목록 보기
6/11
post-thumbnail

컴파일 과정

컴파일 : 소스코드를 CPU가 이해할 수 있는 기계어 코드(오브젝트 코드)로 바꾸는 것

컴파일 과정 : 실행 파일이 나오기 까지

  1. hello.c ==> preprocessor(전처리기) ==> hello.i
  2. hello.i ==> compiler(컴파일러) ==> hello.s (어셈블리어)
  3. hello.s ==> Assembler(어셈블러) ==> hello.o (기계어)
  4. hello.o ==> Linker(링커) ==> hello.exe / hello.elf

확장자가 모두 다릅니다. 보통 컴파일 할 때에는 i/s 파일은 사용자에게 보여줄 필요가 없어 보여주지 않는다.

전처리기 지시문 예제

전처리기 지시문 (#include , #define) 을 처리한다.

#include <stdio.h>

#define PAI 3.141592653589796264338

int main()
{
	printf("%30.10lf\n", PAI);

	// 미리 정의된 매크로 사용 , _2개씩이다.
	printf("File :%s\n", __FILE__);
	printf("Date :%s\n", __DATE__);
	printf("Time :%s\n", __TIME__);
	printf("Line :%d\n", __LINE__);


	return 0;
}

출력

i파일 보기 위한 편한 세팅

Eclipse에서는 i파일 보는 방법이 불편하므로, VS를 통해 i파일을 쉽게 보자.

프로젝트 > 속성 >

Crtl + F7을 통해 전처리 해보기

을 통해 해당 파일에 .i 파일을 찾아 VS창 옆에 띄우기

전처리기 연습

define

글자 그대로 치환한다.
main.c

#include "hi.h";
#define MAX 99

int main()
{
	int a = abc(200);

	a = MAX + MAX;

	return 0;
}

main.i



int abc(int i);



int main()
{
	int a = abc(200);

	a = 99 + 99;

	return 0;
}

조건부 컴파일

리눅스와 윈도우 둘다 돌아가는 코드를 제작할 수 있습니다.

ifdef ~ endif

정의가 되어있다면 실행 시키기
main.c

#define DEBUG
// #define RELEASE
// 둘다 정의시 전처리 과정에서는 문제없이 2개의 main 함수가 전처리 되지만, 컴파일 과정에서 오류가 발생한다.

// DEBUG가 정의 되어 있으면 아래 코드 실행
#ifdef DEBUG
int main()
{
	int a = 20;
	return 0;
}

#endif

// RELEASE가 정의 되어 있으면 아래 코드 실행
#ifdef RELEASE
int main()
{
	int a = 1000;
return 0;
}

#endif

main.i


// 정의 되지 않은 코드는 날라간걸 확인할 수 있다.

int main()
{
	int a = 20;
	return 0;
}

undef

정의 된것 지우기
main.c

#define DEBUG

// DEBUG가 정의 되어 있으면 RELEASE 정의
#ifdef DEBUG
#define RELEASE
#endif

#ifdef RELEASE // REALEASE 정의 되었기 때문에 실행
int main()
{
	int a = 20;
	return 0;
}
#define ABC // ABC 정의
#endif
#undef ABC // 정의된 ABC 삭제
#ifdef ABC // ABC 정의 되어있지 않으므로 실행 x
int main()
{
	int a = 1000;
	return 0;
}
#endif

main.i


int main()
{
	int a = 20;
	return 0;
}


else & ifndef

if구문에서 else와 if-not 구문
main.c

#define ABC
#define DEF

#ifdef ABC // ABC 정의되어 있으므로
#define CCC // CCC 정의됨
#else // ABC 정의 되어있지 않다면 실행
#undef DEF
#undef QQQ
#endif

#ifndef QQQ // QQQ가 정의되어 있지 않다면 실행
#define QQQ // QQQ 정의
#endif

#ifdef QQQ // QQQ가 정의되어 있어서
HAHA
#endif

main.i

HAHA

if , elif , else, endif

ifdef와 달리 정의 된것에 대한 조건문이 아닌 값에 대한 조건문이다.
main.c

#define BTS 10

// BTS 값에 따라 전처리 되는것이 달라진다.
#if BTS == 5
멤버 5#elif BTS == 7
멤버 7#else 
멤버 10#endif

main.i

멤버 10명

#if 0을 통해 주석처리 가능, 코드를 포함시키지 않는 용도로 사용된다. 코드를 지우지 않고 잠시 실행시키고 싶지 않을 때 사용한다.

if defined

defined를 사용하면 && , || , == , !=, > , < 등 연산기호 사용 가능
main.c

#define ABC
#define DEF

// ABC와 DEF 둘다 정의 되어 있으므로 10000 전처리 됨
#if defined ABC && defined DEF
10000
#endif

main.i

10000

매크로 함수

함수 호출이 아니므로 속도가 빨라진다. but) 코드 사이즈가 늘어남(메모리 낭비)
따라서, 적당히 사용하는게 좋다.
main.c

#include <stdio.h>
#define SUM(a,b) (a+b) // 괄호가 반드시 있어야 연산 오류가 나지 않는다.
// 함수가 아닌 매크로임을 명심하자!

int main()
{
	printf("%d", SUM(3, 5)*10);  // a와 b가 3과 5로 치환된다.

	return 0;
}

main.i

int main()
{
	printf("%d", (3+5) * 10); // 80
    // 괄호 없었을 시 : printf("%d", 3 + 5 * 10) 가 되어 53이 된다.

	return 0;
}

# 사용

""을 표현할 수 있습니다.
main.c

#include <stdio.h>
#define ABC(x) #x

int main()
{
	printf(ABC(3));

	return 0;
}

main.i

int main()
{
	printf("3");

	return 0;
}
profile
여러 방향으로 접근하는 개발자

0개의 댓글