티스토리 뷰
선행처리기와 매크로
실행파일은 선행처리, 컴파일, 링크의 과정을 거쳐서 만들어진다.
선행처리가 하는 일은 삽입해 놓은 선행처리 명령문대로 소스코드의 일부를 수정하는 것이다.
ex) #define PI 3.14 =>PI를 3.14로 수정
#include<stdio.h>도 선행처리 명령문(stdio.h 파일의 냉요을 이곳에 가져다 놓으세요)
대표적인 선행처리 명령문
#define : Object-like macro
#define PI 3.1415
지시자 매크로 매크로 몸체
이어서 등장하는 매크로(PI)를 마지막에 등장하는 매크로 몸체(3.1415)로 치환하라
PI와 같은 매크로를 오브젝트와 유사한 매크로, 또는 매크로 상수라고 한다. 매크로는 대문자로
#include <stdio.h>
#define NAME "홍길동"
#define AGE 24
#define PRINT_ADDR puts("주소: 경기도 용인시\n");
int main(void)
{
printf("이름: %s \n", NAME);
printf("나이: %d \n", AGE);
PRINT_ADDR;
return 0;
}
#define : Function-like macro
매개변수가 존재하는 매크로는 '함수와 유사한 매크로', 또는 '매크로 함수'라 부른다.
#define SQUARE(X) X*X
이러한 패턴 등장시 이러한 유형으로 바꿔라
#include <stdio.h>
#define SQUARE(X) X*X
int main(void)
{
int num = 20;
/* 정상적 결과 출력 */
printf("Square of num: %d \n", SQUARE(num));
printf("Square of -5: %d \n", SQUARE(-5));
printf("Square of 2.5: %g \n", SQUARE(2.5));
/* 비정상적 결과 출력 */
printf("Square of 3+2: %d \n", SQUARE(3 + 2));
return 0;
}
잘못된 매크로 정의
SQUARE(3+2) 함수의 관점에서 보면 5*5=25인데 결과가 11이야 ????
=> 3+2*3+2 =>해결책은??? => SQUARE((3+2)) => (3+2)*(3+2) => 이건 안정적이지 못하잖아
매크로 몸체에 괄호를 마구마구 칩시다
#define SQUARE(X) (X)*(Y) => SQUARE(3+2)해결
BUT int num=120/SQUARE(2) => 120/2*2라서 나눗셈이 먼저 진행
#define SQUARE(X) ((X)*(Y)) => 120/((2)*(2));
매크로를 두 줄 이상에 걸쳐서 정의할 때에는 \문자를 활용해서 줄이 바귀었음을 명시
매크로 정의 시, 먼저 정의된 매크로도 사용 가능
#include <stdio.h>
#define PI 3.14
#define PRODUCT(X, Y) ((X)*(Y))
#define CIRCLE_AREA(R) (PRODUCT((R), (R))*PI)
int main(void)
{
double rad = 2.1;
printf("반지름 %g인 원의 넓이: %g \n", rad, CIRCLE_AREA(rad));
return 0;
}
매크로 함수의 장점
1. 일반 함수에 비해 실행속도가 빠르다.
2. 자료형에 따라서 별도로 함수를 정의하지 않아도 된다.
빠른 이유 : 함수가 호출되면
1. 호출된 함수를 위한 스택 메모리의 할당
2. 실행위치의 이동과 매개변수로의 인자 전달
3. return 문에 의한 값의 반환
매크로 함수의 단점
1. 정의하기가 정말로 까다롭다.
2. 디버깅하기가 쉽지 않다.
#include <stdio.h>
#define DIFF_ABS(X, Y) ( (x)>(y) ? (x)-(y) : (y)-(x) )
int main(void)
{
printf("두 값의 차: %d \n", DIFF_ABS(5, 7));
printf("두 값의 차: %g \n", DIFF_ABS(1.8, -1.4));
return 0;
}
=> 대, 소문자가 달라서 오류가 뜬다. 그런데 오류를 찾기가 쉽지 않다.(정말?? 그렇다고 하네요)
매크로 함수로 정의하는 함수
1. 작은 크기의 함수
2. 호출의 빈도수가 높은 함수
조건부 컴파일을 위한 매크로
#if...#endif:참이라면
#include <stdio.h>
#define ADD 1
#define MIN 0
int main(void)
{
int num1, num2;
printf("두 개의 정수 입력: ");
scanf_s("%d %d", &num1, &num2);
#if ADD
printf("%d + %d = %d \n", num1, num2, num1 + num2);
#endif
#if MIN
printf("%d - %d = %d \n", num1, num2, num1 - num2);
#endif
return 0;
}
#ifdef... #endif:정의되었다면(아래 식에 1,0빼도 돼 => 소스코드에 있는 ADD, MIN은 소멸)
#include <stdio.h>
// #define ADD 1
#define MIN 0
int main(void)
{
int num1, num2;
printf("두 개의 정수 입력: ");
scanf("%d %d", &num1, &num2);
#ifdef ADD
printf("%d + %d = %d \n", num1, num2, num1 + num2);
#endif
#ifdef MIN
printf("%d - %d = %d \n", num1, num2, num1 - num2);
#endif
return 0;
}
#ifndef... #endif:정의되지 않았다면(헤더파일의 중복포함을 막기 위해 주로 사용)
#else의 삽입 : #if, #ifdef, #ifndef에 해당
#elif의 삽입 : #if에만 해당(else if)
매개변수의 결합과 문자열화
문자열 내에서는 매크로의 매개변수 치환이 발생하지 않습니다.
문자열 내에서 매크로의 매개변수 치환이 발생하게 만들기 : #연산자
#define STR(ABC) #ABC
매개변수 ABC에 전달되는 인자를 문자열 "ABC"로 치환해라!
#include <stdio.h>
#define STRING_JOB(A, B) #A "의 직업은 " #B "입니다."
int main(void)
{
printf("%s \n", STRING_JOB(이동춘, 나무꾼));
printf("%s \n", STRING_JOB(한상순, 사냥꾼));
return 0;
}
특별한 매크로 연산자 없이 단순히 연결하는 것은 불가능합니다.
#include <stdio.h>
// #define STNUM(Y, S, P) YSP
// #define STNUM(Y, S, P) Y S P
#define STNUM(Y, S, P) ((Y)*100000+(S)*1000+(P))
int main(void)
{
printf("학번: %d \n", STNUM(10, 65, 175));
printf("학번: %d \n", STNUM(10, 65, 075));
return 0;
}
형태대로 단순하게 결합하기 : 매크로 ## 연산자
#define STNUM(Y, S, P) Y ## S ## P
'책 > 윤성우 열혈 C 프로그래밍' 카테고리의 다른 글
파일의 분할과 헤더파일의 디자인 (0) | 2020.09.26 |
---|---|
메모리 관리와 메모리의 동적 할당 (0) | 2020.09.24 |
파일 입출력2 (0) | 2020.09.24 |
파일 입출력1 (0) | 2020.09.23 |
구조체와 사용자 정의 자료형2 (0) | 2020.09.21 |