본문 바로가기
대외활동/시스템프로그래밍

1주차 C 전처리, 매크로, 조건부 컴파일

by hoshi03 2024. 7. 19.

• 전처리

소스 파일 -> 전처리 -> 컴파일 -> 링크 단계를 통해 소스파일을 실행파일로 변환한다

 

-전처리 

hello.c -> hello.i

소스파일이 전처리 단계를 통해 #으로 시작하는 #include나 #define 등의

헤더 파일이나 상수, 매크로등을 처리한다

#ifdef, #endif 등의 지시문도 전처리 과정에서 처리되어 코드블록의 포함 여부를 결정한다

전처리 단계가 끝나면, 소스 코드의 텍스트가 전처리문에 따라 수정된 상태가 된다

 

-컴파일

hello.i -> hello.s나 hello.obj

컴파일러가 고수준 언어를 저수준으로 변환

구문 분석, 어셈블리 코드 생성, 최적화등의 작업을 진행해

소스 프로그램을 목적 프로그램으로 변환한다

 

-어셈블

hello.s -> hello.o

어셈블러가 어셈블리어를 기계어로 변환하고 오브젝트 파일을 생성한다

 

-링크

hello.o -> hello.exe

링커가 오브젝트 파일을 합치고, 라이브러리도 합친다

목적 프로그램을 라이브러리와 합쳐서 exe 프로그램을 생성한다

 

요약

  1. 전처리: #define, #include, #ifdef 등 전처리 지시문을 처리하여 소스 코드를 수정.
  2. 컴파일: 전처리된 소스 코드를 어셈블리어 또는 중간 코드로 변환.
  3. 어셈블: 어셈블리어 코드를 기계어로 변환하여 오브젝트 파일 생성.
  4. 링크: 여러 오브젝트 파일과 라이브러리 파일을 결합하여 실행 파일 생성.

• 매크로 함수, 매크로 상수

#define MAX 10
#define SUM(a, b) ((a) + (b)) //연산자 우선순위 떄문에 가로를 철저하게 사용하는 매크로 함수
#define MUL(a, b) ((a) * (b))

 

#define 다음에 상수나 함수를 작성한다. 함수는 연산자 우선순위 처리를 위해 괄호를 확실하게 묶어준다

 

• 매크로 비트 연산자

 

#define _CRT_SECURE_NO_WARNINGS    
#include <stdio.h>
#include <stdlib.h>

#define bitset(x, bit) ((x) |= (1 << (bit)))
#define shift_left(x, bit) ((x) << (bit))

#define bitClear(x, bit) ((x) &= (~(1<<(bit))))
#define bitFlip(x, bit) ((x) ^= (1<<(bit)))
#define bitIsSet(x, bit) ((x)&(1 << bit))

int main() {
    unsigned cnum = 0x16;
    printf("%x\n", cnum);

    bitClear(cnum, 2);
    printf("%x\n", cnum);

    bitClear(cnum, 1);
    printf("%x\n", cnum);

    bitFlip(cnum, 2);
    printf("%x\n", cnum);

    if (bitIsSet(cnum,3)) printf("비트 올바르게 들어있음");
}

 

0x16을 매크로 함수로 비트 변경하기

 

00010110 - 0x16 시작
00010010 - bitclear 2
00010000 - bitclear 1
00010200 - bitflip 2

 

• 매크로 ## 연산자

 

#define NAME_CAT(x,y) ( x ##y)

 

int a1;

NAME_CAT(a, 1) = 10; / a1 = 10과 동일하게 작동한다

 

• 조건부 컴파일

#if

#ifdef

#else

#endif

#elif

#ifndef

 

조건부 컴파일 지시자를 이용해서 선택적으로 컴파일 되게 조절할 수 있다

예제처럼 언어별 대응을 하거나, os 환경에 따라 문법이 바뀌는 부분을 대응할 수 있다

#define LANG 1

int main(){
...
#if (LANG == 0)
        printf("1 : 입력\n");
        printf("2 : 출력\n");
        printf("3 : 검색\n");
        printf("4 : 삭제\n");
        printf("5 : 삽입\n");
        printf("9 : 종료\n");
        printf("선택 --> ");

#else (LANG != 0)
        printf("1 : Enter\n");
        printf("2 : Print\n");
        printf("3 : Search\n");
        printf("4 : Delete\n");
        printf("5 : Insert\n");
        printf("9 : Quit\n");
        printf("선택 --> ");
#endif // DEBUG
}

 

• pragma

 

#pragma once로 헤더파일 중복을 방지한다

#pragma pack을 이용해서 구조체 크기 단위를 설정한다

#define _CRT_SECURE_NO_WARNINGS    
#include <stdio.h>
#include <stdlib.h>

#pragma pack(push,1)

typedef struct {
	char ch;
	int in;
} s1 ;

#pragma pack(pop)

typedef struct {
	char ch;
	int in;
} s2;


int main() {
	printf("%d\n", sizeof(s1));
	printf("%d\n", sizeof(s2));
}

 

 

'대외활동 > 시스템프로그래밍' 카테고리의 다른 글

임베디드 C  (4) 2024.07.22
리눅스 C 환경설정  (0) 2024.07.22
volatile 지시자  (0) 2024.07.19
1주차 C 공용체,열거형,파일 입출력  (0) 2024.07.19
1주차 C 기초부터 이중연결리스트까지  (0) 2024.07.18