C언어 매크로 사용법 (2/2. 함수 매크로)

2024. 8. 3. 12:45프로그래밍 언어/C

소스 코드에서 반복적으로 사용되는 코드를 간단하게 정의하고 사용할 수 있게 해주는 전처리기(preprocessor) 기능 중 하나로 #define 지시어를 사용하여 정의된다.

전처리 단계에서 처리하므로 컴파일 이전에 모두 치환된다. 어느 단계에서 처리가 되는지 아는 것도 중요하다.

 

매크로는 전처리 단계에서 단순 텍스트 치환이기 때문에 속도는 빠르다, 다만 주의할 점이 많으므로 숙지하고 습관화해야 하는 부분이 존재한다.

 

* 함수 매크로를 사용한 예제들을 확인해보자.

간단한 수학 연산

예시 (ChatGPT 생성):

#include <stdio.h>

#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))

int main() {
    int num1 = 4, num2 = 7;
    printf("Square of %d: %d\n", num1, SQUARE(num1));
    printf("Max of %d and %d: %d\n", num1, num2, MAX(num1, num2));
    printf("Min of %d and %d: %d\n", num1, num2, MIN(num1, num2));
    return 0;
}

[여기서 내용 추가]

 

 SQUARE(x) ((x) * (x)) 이 함수 매크로를 보면 매개변수인 x를 (x)로 묶어 두었다. 이는 매크로가 단순 치환이라는 부분에서 주요한 부분이다.

 

 예를 들면 SQUARE(1+2)라고 적었다고 생각해보자 SQUARE(x) ((x) * (x)) 로 선언한 것과 SQUARE(x) (x * x) 라고 선언한 것의 결과가 달라질 것이다. SQUARE(x) (x * x)처럼 ()없이 선언했다면 1+2 * 1+2 로 치환되고 곱샘이 먼저 연산되므로 엉뚱한 결과가 나왔을 것이다. 따라서 매크로 함수를 사용할 때 매개변수는 항상 ()로 묶는 것을 습관화해서 이러한 오류가 발생하지 않도록 하는 것이 중요하다. (필드에서 생각보다 이러한 이유로 인한 오류가 종종 나온다.)

 

- SQUARE(x) ((x) * (x)) - 맞는 사용방법

- SQUARE(x) (x * x) - 문제가 있는 사용방법

 

 

디버깅용 매크로

디버깅 정보를 출력하는 매크로를 정의해서 디버깅시 활용 가능

 

예시 (ChatGPT 생성):

#include <stdio.h>

#define DEBUG

#ifdef DEBUG
    #define DEBUG_PRINT(x) printf("DEBUG: %s = %d\n", #x, x)
#else
    #define DEBUG_PRINT(x)
#endif

int main() {
    int value = 42;
    DEBUG_PRINT(value);  // DEBUG 모드에서만 출력됨

    value = 100;
    DEBUG_PRINT(value);  // DEBUG 모드에서만 출력됨

    return 0;
}

 

안전한 메모리 해제

매크로를 사용하여 메모리 해제를 안전하게 수행할 수 있다. (반복되는 코드이며 메모리 해제시 절차가 누락되면 버그의 원인이 되는 코드.)

 

예시 (ChatGPT 생성):

#include <stdlib.h>

#define SAFE_FREE(ptr) do { \
    if (ptr) {              \
        free(ptr);          \
        ptr = NULL;         \
    }                       \
} while(0)

int main() {
    int *data = (int *)malloc(100 * sizeof(int));
    // 메모리 사용 코드
    SAFE_FREE(data);  // 메모리 해제와 NULL 설정
    return 0;
}

[여기서 내용 추가]

#define SAFE_FREE(ptr) do { \ if (ptr) { \ free(ptr); \ ptr = NULL; \ } \ } while(0)

에서 do { 여러 줄의 코드 } while(0)으로 그냥 보기에는 의미 없는 반복문으로 코드를 감싸 놓은 것처럼 보인다.

 

이는 일종의 함수 매크로를 사용하는 기술로 1. 코드의 끝에 ; 붙이는 C언어 특성 / 2. do ~ while의 중괄호 안의 scope를 활용할 수 있고 / 3. 매크로를 만든 의도대로 특정 단위코드를 감싸주는 역할 등 사용하는 이유가 존재한다. (상세한 설명은 다음에 또 다뤄보도록하고 매크로 함수를 여러 줄의 코드로 작성하는 경우 습관적으로 do ~ while(0)으로 묶어주도록 하자.)

 

배열 크기 계산

배열의 크기를 계산하는 매크로

예시 (ChatGPT 생성):

#include <stdio.h>

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    printf("Array size: %lu\n", ARRAY_SIZE(numbers));
    return 0;
}

 

 

비트 연산 매크로

비트 연산을 수행하는 매크로

예시 (ChatGPT 생성):

#include <stdio.h>

#define SET_BIT(value, bit) ((value) |= (1 << (bit)))
#define CLEAR_BIT(value, bit) ((value) &= ~(1 << (bit)))
#define TOGGLE_BIT(value, bit) ((value) ^= (1 << (bit)))
#define CHECK_BIT(value, bit) (((value) >> (bit)) & 1)

int main() {
    int flags = 0;
    
    SET_BIT(flags, 1);  // 1번 비트를 설정
    printf("Flags after setting bit 1: %d\n", flags);
    
    TOGGLE_BIT(flags, 1);  // 1번 비트를 토글
    printf("Flags after toggling bit 1: %d\n", flags);
    
    CLEAR_BIT(flags, 1);  // 1번 비트를 클리어
    printf("Flags after clearing bit 1: %d\n", flags);
    
    int bitStatus = CHECK_BIT(flags, 1);  // 1번 비트 상태 확인
    printf("Bit 1 status: %d\n", bitStatus);
    
    return 0;
}

 

매크로 사용 시 주의사항

  • 텍스트 치환: 예상치 못한 결과를 방지하기 위해 항상 매크로 매개변수를 괄호로 감싸도록 하자.
  • 디버깅 어려움: 디버깅시 매크로로 치환되는 부분의 경우 디버깅이 어렵고, 작성된 코드는 짧지만 분석해야하는 코드의 복잡도를 증가하게 하기도 함.
  • 안정성 등의 측면에서 불리하므로 inline 함수를 사용하는 것을 먼저 고려해보도록 하자.

 

참고:

 

https://ko.wikipedia.org/wiki/%EB%A7%A4%ED%81%AC%EB%A1%9C

 

매크로 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 매크로(macro, 문화어: 마크로)는 "macroscopic"에서 나온 말로, 다음의 형태로도 쓰인다. <!-- NewPP limit report Parsed by mw‐api‐ext.eqiad.main‐5874bfb84f‐5gq78 Cached time: 202407

ko.wikipedia.org

https://www.geeksforgeeks.org/macros-and-its-types-in-c-cpp/

 

Macros and its types in C - GeeksforGeeks

A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.

www.geeksforgeeks.org