C 언어 - 전처리 지시자

Ohyuchan·2023년 9월 26일
0

🧑🏻‍💻 C Language

목록 보기
15/18
post-thumbnail

📁 전처리 지시자


이번 포스팅에서는 전처리 지시자에 대해서 작성해보려고 합니다.
대부분의 전처리 지시자들은 세 가지로 분류될 수 있습니다.

  • 매크로 정의(macro definition) : #define 지시자는 매크로를 정의해준다
    #undef 지시자는 매크로 정의를 없애준다
  • 파일 추가(file inclusion) : #include 지시자는 특정 파일의 내용물을 프로그램에 추가해준다.
  • 조건적 컴파일(conditional compilation) #if, #ifdef, #ifndef,
    #elif,#else, `#endif 지시자들은 전처리가 확인할 주어진 조건에 따라 코드의 특정 부분을 프로그램에서 추가하거나 제외할 수 있다.

나머지 지시자들인 #error, #line, #pragma는 좀 더 특수한 목적을 갖고 있어 그리 자주 사용되지는 않는다.

👉 지시자의 규칙


전처리 지시자에 대해서 정리하기 전에, 모든 지시자들에 적용되는 몇 가지 규칙을 알아보도록 하자

  • 지시자는 언제나 # 기호로 시작한다. # 기호 이전에 공란문자가 있기만 하면 굳이 해당 줄은 반드시 # 기호로 시작할 피요는 없다. # 기호 이후에는 지시자의 이름과 해당 지시자가 필요로 하는 다른 정보들이 온다
  • 지시자의 토큰 사이에는 띄어쓰기와 수평탭이 임의의 개수만큼 들어갈 수 있다.
#define N (100)
  • 지시자는 명시적으로 이어붙히지 않는 한 반드시 첫번째 개행문자로 끝나야 한다.
    지시자를 다음 줄로 넘겨주려면 반드시 현재 줄을 \ 문자로 끝내야 한다
#define DISK_CAPACITY (SIDES *             \
                       TRACKS_PER_SIDE *   \
                       SECTORS_PER_TRACK * \
                       BYTES_PER_SECTOR)
  • 지시자는 프로그램 어디서든 등장할 수 있다. 주로 #define이나 #include 지시자를 파일의 시작부에 놓기는 하지만 다른 지시자들은 나중에, 심지어 함수 정의 중간에서도 나올 가능성이 더 높다.
  • **주석은 지시자와 같은 줄에 나올 수도 있다. 크로 정의 끝부분에 주석을 놓아서 매크로의 의미를 설명해주는 것이 좋은 코딩 습관이다

👉 매크로 정의


매크로 함수는 함수처럼 인자를 설정할 수 있는 매크로를 의미합니다.
매크로 상수와는 달리 매크로 함수 이름에 괄호 와 함께 인자 목록이 주어져 있습니다.
매크로 함수라고 부르지만 단순히 치환하기만 하므로 실제로 함수는 아닙니다.

함수 선언과 비슷하지만 매크로 함수는 인자의 자료형을 신경 쓰지 않습니다.
즉, 자료형의 독립성을 보장합니다. 또 매크로 함수 내부에서 자기 자신을 호출할 수 없다는 특징이 있습니다.
매크로를 정의하는 경우에는 컴파일이 되면 해당 매크로 이름을 가진 것들이 지정해놓은 값으로 변해서 컴파일 됩니다.

📝 매크로 함수 사용법


#define (매크로 함수 이름) (매크로 함수 기능)
#define ADD(a,b) a+b //ex

`#define으로 시작되는 전처리 문장을 매크로라고 하며 이를 사용하여 매크로 함수를 만들 수 있습니다.

매크로 함수 사용 예제

#include <stdio.h>

#define ADD(x,y) x+y

int main()
{
    int num1 = 10;
    int num2 = 20;

    printf("매크로 함수(ADD) : %d + %d = %d\n", num1, num2, ADD(num1, num2));

    return 0;
}

😡 매크로 함수 사용 시 주의점


#include <stdio.h>

#define MUL1(x,y) x*y
#define MUL2(x,y) (x)*(y)

int main()
{
    int num1 = 5;
    int num2 = 4;

    printf("매크로 함수(MUL1) : %d * %d = %d\n", num1 + 1, num2 + 1, MUL1(num1 + 1, num2 + 1));  // num1 + 1 * num2 + 1로 변환
    printf("매크로 함수(MUL2) : %d * %d = %d\n", num1 + 1, num2 + 1, MUL2(num1 + 1, num2 + 1));  // (num1 + 1) * (num2 + 1)로 변환

    return 0;
}

Alt text

매크로 함수는 num1+1, num2+2를 단순히 x와 y의 위치에서 단순히 치환하기 때문에 괄호를 제대로
사용하지 않는다면 위와 같은 문제점이 발생할 수 있습니다.
곱셈처럼 연산순서에 따라 결과가 달라질 수 있다면 어떠한 인자값이 들어올 지 모르니 매크로 함수의
기능에 명시적으로 괄호를 처리해주어 잘못 연산되는 것을 방지해야 한다

ex. 안 좋은 예시 : ADD(x, y) x + y
좋은 예시 : ADD(x,y) ((x) + (y))

📄매크로 함수와 인라인 함수의 공통점과 차이점

매크로 함수와 인라인 함수는 작동방식과 결과에 대해서는 매우 유사하지만 차이점도 있습니다.

  • inline 함수의 경우
    컴파일 단계(Compiling)에서 처리가 이루어집니다. (인라인 하느냐 vs 안되느냐)
    일반적인 함수들을 위해 실행하는 타입 검사가 그대로 적용됩니다.

  • macro 확장자의 경우
    전처리 단계(Preprocessing)에서 치환이 이루어집니다.
    대치 시 어떠한 타입 검사도 이루어지지 않습니다.

👉 파일 추가


⇲ stdio.h


Standard Input Output, 즉 표준 입출력을 의미한다. studio가 아니다.
C언어를 처음 접하는 사람들이 많이 실수하는 부분이다(가끔씩 자동완성 안 뜨고 급하게 작성하다 보면
실수 할 때가 많다)

C언어의 표준 입/출력 헤더 파일로, printf나 scanf 처럼 콘솔 입/출력을 할 때, 외부 파일을
읽을 때 사용한다. 기초 프로그래밍 교육이 대부분 Hello World 출력부터 시작해, 대부분 CLI
환경을 다루는 것에 그친다는 것을 생각하면, C/C++을 배우면서 자주 보게 되는 헤더 파일이다.

⇲ time.h

시간 관련 부분함수 구조체를 담고있는 헤더로 시간관련 부분을 불러오거나 사용할 때 사용한다

⇲ math.h

지수함수, 로그함수, 삼각함수, 거듭제곰 등 수학 관련 함수가 들어가 있다

⇲ stdlib.h


문자열 변환, 의사 난수 생성, 동적 메모리 관리 등의 함수들을 포함하고 있다.
주로 프로그램 제어 관련 함수가 들어가 있다. 동적 메모리 할당 함수인
malloc, calloc 함수도 이 헤더에 포함되어 있으며, 시스템 명령어나 프로세스 제어 함수도 포함되어 있다.

⇲ string.h


문자열(정확히는 문자 배열 - char* str 또는 char str[]) 관련 헤더이다.

  • strcat - 문자열 합치기
  • strcmp - 문자열 비교
  • strlen - 문자열 길이
  • strcpy - 문자열 복사

등의 함수가 있다.

profile
안녕하세요

0개의 댓글