매크로와 선행처리기

2023. 5. 31. 22:31·CS 이론/학과 수업
728x90

선행처리는 컴파일 이전의 처리를 의미한다.

일반적으로 컴파일의 과정에 포함이 되어 이야기하지만, 선행처리의 과정과 컴파일의 과정은 구분이 된다.

 

선행처리기가 하는 일의 예시를 보면

#define PI 3.14가 의미하는 것은 "PI를 3.14로 치환하라"이다.

컴파일러에 비해서 선행처리기의 역할은 매우 간단하다. '단순한 치환'의 작업을 거친다. 그리고 선행처리기에게 무엇인가를 명령하는 문장은 #으로 시작한다.

 

 

 

위에처럼 변수 대신 함수 형식으로 매크로를 만드는 방법으로 확장된다.

여기서 당연히 결과가 25로 나올거라고 생각하겠지만 결과는 11로 나왔다. 그 이유는 뭘까?

 

이유는 SQUARE(X) X*X일때 3+2*3+2로 되어서 11이된다.

그래서 이런 문제를 해결하기 위해서는 (X)*(X)로 해야한다.

하지만 이런 경우 num = 120/SQUARE(2)의 경우 120/(3+2)*(3+2)로 되어서 그대로 120이 나온다.

그래서 아래와 같이 수정을 해야한다.

 

매크로에 대해 좀 더 보면

두줄에 이어서 매크로를 정의하려면 \를 이용해야한다.

#define SQUARE(X) \
((X)*(X))

그리고 먼저 정의된 매크로를 다른 매크로를 정의하는데 사용할 수 있다.

일반함수와 비교했을 때 매크로 함수의 장점은 무엇일까?

  • 매크로 함수는 일반 함수에 비해 실행속도가 빠르다.
    • 함수의 호출을 완성하기 위해서는 별도의 메모리 공간이 필요하고 호출된 함수로의 이동 및 반환의 과정을 거쳐야 한다. 반면 매크로 함수는 정의된 몸체로 치환이 이뤄지니 이러한 일이 불필요하며, 때문에 실행속도가 빨라질 수 밖에 없다.
  • 자료형에 따라서 별도로 함수를 정의하지 않아도 된다.
    • 전달되는 인자의 자료형에 구분을 받지 않으므로 자료형에 의존적이지 않다.

단점은 무엇일까?

디버깅이 어렵고, 정의하기가 까다롭다.

왜냐하면 오류를 발견하는건 선행처리 후 컴파일러에 의해서 에러가 감지되기 때문에 디버깅이 어렵다.

 

그래서 함수를 매크로로 정의하는 것의 조건은 두 가지이다.

호출의 빈도수가 높고, 크기가 작은 간단한 함수이어야한다.

한 두줄 정도 크기의 작은 함수가 아니면 매크로로 정의하는 것이 쉽지 않아서 오류발생 확률이 높아진다. 그리고 if~else와 같이 실행의 흐름을 컨트롤 하는 문장도 매크로로 정의하기 쉽지 않다.

함수를 매크로로 정의하는 데에는 성능적 측면이 고려된다. 그런데 호출의 빈도수가 높지 않으면 애써 매크로로 함수를 정의하는 수고를 할 이유가 줄어든다.

 

#if #endif와 #ifdef #endif, #ifndef #endif의 세가지 경우로 조건을 사용할 수도 있다.

또한 #else를 추가할 수도 있다.

 

그리고 #if의 경우 #elif또한 사용할 수 있다.

이는 함수의 조건문과 비슷하기 때문에 쉽게 이해할 것이다.

 

이번에는 매크로로 문자열 내부의 매개변수를 치환하는 것에 대해서 알아보자

[문자열 치환 목적으로 정의된 매크로]

#define STRING_JOB(A, B) "A의 작업은 B입니다."

치환의 대상이 되는 A와 B가 문자열 안에 존재함에 주목하자!

 

[매크로의 확장 결과]

STRING_JOB(이동춘, 나무꾼) -> "A의 직업은 B입니다."
STRING_JOB(한상순, 사냥꾼) -> "A의 직업은 B입니다."

이동춘과 나무꾼, 그리고 한상순과 사냥꾼이 기대대로 치환되지 않았다. 문자열 안에서는 치환이 일어나지 않기 때문이다. 이럴때 고려해 볼 수 있는 연산자가 # 연산자이다!

 

문자열 내에서 매크로 매개변수 치환: #연산자

[# 연산자를 이용해서 정의된 매크로]

#define STR(ABC) #ABC

매개변수 ABC에 전달되는 인자를 문자열 “ABC”로 치환해라!

 

[# 연산자 기반의 매크로 확장 결과]

STR(123) -> "123"
STR(12,23,34) -> "12, 23, 34"

 

#연산자를 활용해서 이 문제를 해결할 수 있다.

그렇다면 문자열이 아닌 단순 연결은 어떨까?

여기에는 또 문제점이있다.

그래서 ##연산자로 이를 해결한다. 필요한 형태대로 단순결합을 할 수 있다.

[##연산자를 이용해서 정의된 매크로]

#define CON(UPP, LOW) UPP ## 00 ## LOW

매개변수 UPP와 LOW에 전달되는 인자를 UPP00LOW로 단순히 연결해서 치환해라!

[##연산자 기반의 매크로 확장 결과]

int num = CON(22,77); -> 220077

이렇듯 ## 연산자를 이용해서 다음과 같이 매크로를 정의해야 학번을 단순치환 할 수 있다.

 

#define STNUM(Y,S,P) Y ## S ## P

728x90

'CS 이론 > 학과 수업' 카테고리의 다른 글

논리회로 - 진수표현과 덧셈, 뺄셈, 보수  (1) 2023.06.21
파일의 분할과 다중 파일 컴파일  (1) 2023.05.31
자료구조 undo 구현하기  (0) 2023.04.23
'CS 이론/학과 수업' 카테고리의 다른 글
  • 논리회로 - 진수표현과 덧셈, 뺄셈, 보수
  • 파일의 분할과 다중 파일 컴파일
  • 자료구조 undo 구현하기
Bello's
Bello's
개발하는 벨로
  • Bello's
    벨로의 개발일지
    Bello's
  • 전체
    오늘
    어제
    • 분류 전체보기 (200)
      • 노예 일지 (7)
        • 스타트업 노예일지 (3)
      • CS 이론 (81)
        • 학과 수업 (4)
        • 알고리즘 (64)
        • 시스템 프로그래밍 (3)
        • 데이터 통신 (1)
        • 운영체제 (2)
        • 데이터베이스 (1)
      • project (3)
      • 나는 감자다. (4)
      • Spring (27)
      • 모각코 (45)
        • 절개와지조(모각코) (7)
        • 어쩌다보니 박준태가 조장이조 (11)
        • 어쩌다보니 박준태가 또 조장이조 (12)
      • LikeLion🦁 (20)
      • 캘리포니아 감자 (4)
      • OpenSource Contribute (1)
      • 우아한테크벨로 (8)
        • 프리코스 회고록 (6)
        • Level 1 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    어렵다
    나는 감자
    누적합
    우테코
    BFS
    자바
    8기
    Spring
    DFS
    모각코
    절개와지조
    회고록
    프리코스
    백준
    뛰슈
    타임리프
    그래프 순회
    JPA
    오블완
    감자
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
Bello's
매크로와 선행처리기
상단으로

티스토리툴바