2015년 8월 16일 일요일

C 언어 - 전처리기, typedef, enum

전처리기 (preprocessor)



컴파일러는 전처리문을 읽고 해석하고 처리하여 코드로 변환한 뒤 원래 전처리문은 코드에서 제거한다.

예)
main.c

#define HELLO printf("hello\n")

int main() {
    HELLO;
}

전처리 후


int main() {
    printf("hello\n");
}

  • 위 과정은 컴파일러가 해석하는 부분이기 때문에 정확히 위와 같이 코드가 생성되지는 않겠지만
  • 컴파일 결과물은 전처리 후 코드와 같은 동작을 한다.

아래와 같은 전처리문들이 있다.

  • #include
  • #if
  • #else
  • #elif
  • #endif
  • #define
  • #ifndef
  • #ifdef
  • #error
  • #warning

특징을 보면 # 으로 시작한다는 점을 알 수 있다.

  • #include : 이미 보았겠지만 header 파일을 포함시킨다.
  • #if 조건문 : 분기문
  • #else : #if 조건문이 거짓인 경우
  • #endif : #if 문의 끝
  • #define 정의값 대체문 : 사용자 값 정의
  • #ifndef 정의값 : 정의값이 존재하는지 않는지 판단
  • #ifdef 정의값 : 정의값이 존재하는지 판단
  • #error 경고 문구 : 컴파일 에러 유발 (컴파일 시 경고 문구 출력)
  • #warning 경고 문구 : 컴파일 중 경고 문구 출력

예)

#ifdef __unix__
#    inculde <unistd.h>
#elif define _WIN32
#    include <Windows.h>
#endif

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

#define LOG printf

int main() {
    LOG("Hello World\n");
}

위 코드는 unix 플랫폼일 때와 windows 플랫폼일 때 다르게 변화한다.

unix 플랫폼

#inculde <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("Hello World\n");
}

windows 플랫폼

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("Hello World\n");
}

unistd.h 헤더는 unix 계열 플랫폼에서만 참조할 수 있고 Windows.h 는 windows 계열 플랫폼에서만 참조할 수 있다.

__unix__ 나 _WIN32 등의 define 값은 컴파일러에 의해 미리 정의 된 값이다.

typedef


변수 타입을 추가한다.

문법:
typedef <유효한 C 타입> <새로운 타입명>;

반드시 유효한 C 타입만 typedef 처리할 수 있다.

예)
typedef int mynumber;

...

mynumber number = 10;

mynumber 는 컴파일 과정에서 int 로 대체된다.

예)
  • typedef char mycharacter;
  • typedef char* mystring;
  • typedef unsigned char uint8;
  • typedef unsigned int uint32;

char, short, int 라는 의미보다 데이터 크기가 중요한 경우 type 크기를 이름에 붙이기도 한다.

  • typedef unsigned char myuint8;
  • typedef unsigned short myuint16;
  • typedef unsigned int myuint32;

구조체 변수 선언문을 다시 보면 이렇다.

struct my_struct_t var;

typedef 로 지정하면 아래와 같이 사용할 수 있다.


typedef struct my_struct_t my_struct;

my_struct var;

enum



여러 상수를 열거하는 식으로 선언한다.

예)

enum my_enum {
    left,
    right,
    down,
    up
};

  • 위 문을 실행하면 left, right, down, up 이라는 상수가 자동으로 생성된다.
  • 자동으로 left = 0, right = 1, down = 2, up = 3 값이 지정된다.

마치 이런 코드와 같은 처리를 한다.
const int left = 0;
const int right = 1;
const int down = 2;
const int up = 3;

enum 변수 선언:

enum my_enum var;

enum 변수 참조:

var = left;

enum 변수 비교문:

switch (var) {
case left;
    break;
case right:
    break;
case down:
    break;
case up:
    break;
}

enum 상수 초기값 변경

기본으로 0 1 2 3 ... 순으로 지정이 되지만 초기값을 변경할 수 있다.

예)

enum direction {
    north = 1,
    south,
    west,
    east
};

north 값부터 1씩 더해 간다.
north = 1 ,south = 2, west = 3, east = 4 가 된다.

enum direction {
    north,
    south = 5,
    west,
    east
};

north = 0 ,south = 5, west = 6, east = 7 가 된다.

Cross platform 대응


전처리문 예를 보면 unix 에서 사용할 수 있는 헤더 파일과 windows 에서 사용할 수 있는 헤더 파일이 다르다.
뿐만 아니라. 지원하는 함수들도 다르다.
하지만 일맥상통하는 부분은 같거나 비슷한 기능을 제공하고 있다는 점이다.
다만 함수 이름이나 사용법이 다를 뿐이다.
이런 경우 전처리기와 typedef 문을 잘 활용하면 하나의 소스 코드로 여러 플랫폼에 컴파일 했을 때 문제가 없게 작성할 수 있다.
이러한 처리가 되어 소스 코드 하나로 여러 플랫폼에서 컴파일 할 수 있는 코드를 cross platform 한 코드라고 한다.

댓글 없음:

댓글 쓰기