Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

heenam

Chapter26 매크로와 선행 처리하기 본문

[Programming Language]/C

Chapter26 매크로와 선행 처리하기

znzltiq 2020. 5. 1. 19:16

선행처리기와 매크로

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

  선행처리 과정을 거쳐서 생성되는 파일도 그냥 소스파일일 뿐이다. 왜냐하면 소스파일의 형태가 그래도 유지되기

  때문이다. 선행처리가 하는 일은 지극히 단순하다. 삽입해 놓은 선행처리 명령문대로 소스코드의 일부를 수정할

  뿐인데, 여기서 말한 수정은 단순치환의 형태를 띠는 경우가 대부분이다.

  이처럼 선행처리 명령문은 #문자로 시작을 하며, 컴파일러가 아닌 선행처리기에 의해서 처리되는 문장이기 때문에

  명령문의 끝에 세미콜론을 붙이지 않는다.

   #지시자 매크로 매크로몸체 로 이루어져 있다. *매크로는 대문자로 입력한다.

대표적인 선행처리 명령문

 #define: object-like macro

  #define 지시자는 이어서 등장하는 메크로를 마지막에 등장하는 매크로 몸체로 치환 하라 라는 뜻을 가지고 있다.

#include <stdio.h>

#define NAME "홍길동" //매크로 NAME을 매크로 몸체 홍길동으로 전부 치환하라
#define AGE 24 //매크로 AGE을 매크로 몸체 24로 전부 치환하라
#define PRINT_ADDR puts("주소: 경기도 용인시\n") 
//매크로 PRINT_ADDR을 매크로 몸체 puts로 전부 치환하라

int main()
{
	printf("이름: %s\n", NAME);
	printf("나이: %d\n", AGE);
	PRINT_ADDR;
	return 0;
}

 #define: Function-like macro

  매크로는 매개변수가 존재하는 형태로도 정의할 수 있다. 그리고 이렇게 매개변수가 존재하는 매크로는 그 동작방식이

  마치 함수와 유사하여 '함수와 유사한 매크로'라 하는데, 줄여서 간단히 '매크로 함수'라 부르기도 한다.

  #define SQUARX(X) X*X  // SQUARX괄호안에 있는 X패턴이 등장시 X*X유형으로 바꿔라

 #include <stdio.h>
 #define SQUARX(X) X*X
 
 int main()
 {
 	int name = 20;
	/* 정상적 결과 출력 */
	printf("Square of num: %d\n", SQUARX(num); // 값은 400
	printf("Square of -5: %d\n",  SQUARX(-5)); // 값은 25
	printf("Square of 2.5: %g\n",  SQUARX(2.5)); // 값은 6.25
    
	/* 비정상적 결과 출력 */
	printf("Square of 3+2: %d\n",  SQUARX(3+2)); // 값은 11
	return 0;
 }

 잘못된 매크로 정의

  비정상적 결과 출력의 원인은 3+2*3+2 를 하게 되면 곱하기가 먼저 계산 되고 그다음 덧셈이 계산되기 때문에 우리가

  원하는 값 25가 아닌 11이 출력된다. 따라서 우리가 원하는 값 25를 출력 받고 싶다면 SQUARX((3+2))를 해주면 된다.

  그러면 (3+2)*(3+2)가 되어 우리가 원하는 25를 출력 받을 수 있다.

 매크로 몸체에 괄호를 마구마구 칩시다.

  사칙연산으로 사용할 경우 먼저 계산하고 싶은 곳에 괄호를 쳐 원하는 값을 출력 받을 수 있게 한다.

 매크로를 두 줄에 걸쳐서 정의하려면요?

기본적으로 매크로는 한 줄에 정의 하는 것이 원칙이다.

  따라서 매크로를 두 줄 이상 정의할 때에는 \를 사용해 줄이 바뀌었음을 명시해야 한다.

  #difine SQUARX(X)     /

                X*X         // 이렇게 하게 되면 두 줄 이상 정의할 때에도 사용 가능 하다.

  매크로 정의 시, 먼저 정의된 매크로도 사용이 가능하다.

  #difine a 1

  #difine b 2

  #difine c (a+b) //이처럼 먼저 정의된 매크로를 나중 매크로에 사용할 수 있다.

 매크로 함수의 장점

  + 매크로 함수는 일반 함수에 비해 실행속도가 빠르다.

  + 자료형에 따라서 별도로 함수를 정의하지 않아도 된다.

  실행 속도가 빠른 이유

  + 호출된 함수를 위한 스택 메모리의 할당

  + 실행위치의 이동과 매개변수의 인자 전달

  + return 문에 의한 값의 반환

 매크로 함수의 단점

  + 정의하기가 정말로 까다롭다.

  + 디버깅하기 쉽지 않다.

 그래서 이러한 함수들을 매크로로 정의하지요

  + 작은 크기의 함수

  + 호출의 빈도수가 높은 함수

조건부 컴파일을 위한 매크로

 #if...#endif: 참이라면

#include <stdio.h>
#defiln ADD 1 // 참
#define MIN 0 // 거짓

int main()
{
	int num1, num2;
    printf("두 개의 정수를 입력: ");
    scanf("%d %d", &num1, &num2);
    
    #if ADD // ADD가 '참'이라면
    	printf("%d + %d \n", num1, num2, num1+num2);
    #endif
    
    #if MIN // MIN이 '참'이라면
    	printf("%d - %d \n", num1, num2, num1-num2);
    #endif
    
    	return 0;
        
}

 

#else의 삽입: #if, #ifdef, #ifdef에 해당 과 #elif의 삽입: #if에만 해당

#include <stdio.h>
#define HIT_NUM 5

int main()
{
	#if HIT_NUM == 5
    	puts("매크로 상수 HIT_NUM은 현재 5입니다.")
	#elif HIT_NUM == 6
    	puts("매크로 상수 HIT_NUM은 현재 6입니다.")
	#else
    	puts("매크로 상수 HIT_NUM은 현재 5, 6은 확실히 아닙니다.")
	#endif
    
    	return 0;
}

매개변수의 결합과 문자열화

 문자열 내에서는 매크로의 매개변수 치환이 발생하게 만들기: #연산자

#include <stdio.h>
#define STRING_JOB(A, B)  #A "의 직업은 " #B "입니다."

int main()
{
	printf("%s \n", STRING_JOB(이동춘, 나무꾼);
	printf("%s \n", STRING_JOB(한상순, 사냥꾼);
    
	return 0;
}

 필요한 형태대로 단순하게 결합하기: 매크로 ##연산자

  연산자 사이에 ##를 붙이면 매크로 함수의 전달인자를 다른대상과 이어줄 수 있다.

  #difine CON(UPP, LOW)  UPP ## LOW 

  int num = CON(22, 77) ; // num을 출력 하게 되면 2277 값이 나온다.