c언어

[C언어] 전처리기

kidmillionaire1998 2022. 10. 23. 18:02

-프로그램 개발과 유지보수를 쉽게 하고, 가독성을 높이고, 프로그램 포팅(컴퓨터 A에서 만든 것을 B에서 이식 및 실행)을 쉽게 함 

-#으로 시작하는 행을 전처리 지시자라고 한다. 

#include ... 

#define ... 

#if ... 

 

-전처리 지시자를 위한 구문은 C언어의 나머지 부분과 독립적이다. 

-전처리 지시자가 영향을 미치는 범위는 그 파일에서 전처리 지시자가 있는 위치에서 시작하여 그 파일의 끝까지이거나, 다른 지시자에 의해서 그 지시자의 효혁이 없어질 때까지 이다. 

-전처리기는 C를 알지 못한다. 

 

[매크로] 

여러가지 종류의 매크로 

- 기호상수 (#define N 10) 

- 문자열 대치 

-인자가 있는 매크로 

 

-정의가 길어질 경우에 현재 행의 끝에 역슬래시 \를 삽입하면 다음 행에 연결해서 계속 쓸 수 있다. 

 

-형태 

#define 식별자 상수 

- 프로그램의 모든 식별자상수로 대치된다. 

 

선언 예제 

#define N 60 
#define PI 3.14 
#define C 299792.458  //km/s 

//이미 지정되어있다. 
#define EOF (-1) 
#define NULl 0

기호 상수 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define PI 3.14 

double circumference(double r) {
	return 2.0 * r * PI; 
}

double area(double r) {
	return r * r * PI; 
}

double volume(double r) {
	return 4.0 / 3.0 * r * r * r * PI; 
}

double surface_area(double r) {
	return 4.0 * r * r * PI; 
}

int main(void) {
	double r; 
	printf("반지름을 입력하세요: "); 
	scanf("%lf", &r);
	printf("반지름이 %.3f인 \n", r); 
	printf("원의 원둘레 길이 : %.3f\n", circumference(r)); 
	printf("원의 면적 : %.3f\n", area(r)); 
	printf("구의 부피 : %.3f\n", volume(r)); 
	printf("구의 표면적: %.3f\n", surface_area(r)); 
	return 0; 
}

[실행 결과] 

 

문자열 대치 

형태 

#define 식별자 문자열 

프로그램의 모든 식별자는 문자열로 대치된다. 

 

#define EQ == 
#define AND && 
#define OR ||

 

매개 변수를 갖는 매크로 

- 함수와 비슷한 모양을 가진다. 

예 

#define AREA(x) ((x)*(x)*PI)

//x : 매개변수 
//전처리기는 매개변수를 실인자로 대치한다.

기호 상수 예제를 매개변수를 갖는 매크로를 사용해서 수정 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h> 
#define PI 3.14 
#define CIRCUMFERENCE(x)	(2.0 * (x) * PI)
#define AREA(x)				((x)*(x)*PI)
#define VOLUME(x)			(4.0/3.0 *(x) *(x) *(x) * PI)
#define SURFACE_AREA(x)		(4.0 * (x) *(x)*PI)
int main(void) {
	double r; 
	printf("반지름을 입력하세요: "); 
	scanf("%lf", &r); 
	printf("반지름이 %.3f인 \n", r); 
	printf("원의 원둘레 길이 : %.3f\n", CIRCUMFERENCE(r));
	printf("원의 면적: %.3f\n", AREA(r)); 
	printf("구의 부피: %.3f\n", VOLUME(r)); 
	printf("구의 표면적: %.3f\n", SURFACE_AREA(r)); 
	return 0; 
}

[출력 결과] 

 

Inline 함수 vs 매개 변수를 갖는 매크로 

1. Inline 함수는 컴파일러가, 매크로는 전처리기가 처리한다. 

2. 매크로는 인자의 형을 검사하지 않는다. 

#define AREA(X) ((x)*(x)*PI)

//AREA(3.1) => 그대로 3.1이 들어간다. 

inline int AREA(int n) 
{
	printf("%d",n); 
}
AREA(3.1); 

// int형으로 변환되어 3이 출력된다.

3. 매클는 인자들을 여러번 평가한다. 

#define AREA(x) ((x) * (x) * PI)
AREA(r++)

=> ((r++) * (r++) * 3.14)
로 계산됨

 

[유의사항] 

매크로를 정의할 때 올바른 평가 순서를 유지하기 위해 괄호를 충분히 사용해야한다. 

예시 

#define AREA(x) ((x)*(x)*PI)
#define AREA(X) x * x* PI 


// 4/ AREA(2) 
//AREA(a + b);가 호출 되었을 때, 위 두 문장의 계산결과가 괄호의 유무로 인해 달라진다.

매크로 이름과 매개변수 사이에 공백이 있으면 안된다. 

#define AREA(X) ((x)*(x)*PI) 

#define AREA (x) ((x)*(x)*PI) 

// AREA(5.0)을 호출하게 되면 위의 문장과 다르게 
//(x) ((x)*(x)*PI) (5.0)으로 호출이된다. 
// AREA(X)가 ((x)*(x)*PI)로 대응되는 것이 아니라  
// AREA가 (x) ((x)*(x)*PI)로 대응되는 것이다.

세미콜론 사용에 유의해야한다. 

#define AREA(X) ((x)*(x)*PI);


//위 처럼 define문 뒤에 ;가 붙었을 때, 
// if(r>0) x = AREA(r); else x = -1;이 실행 되었을 때 


//if(r>0) x = ((r)*(r)*PI);;처럼 ;이 중복되어서 실행된다.

 

[#연산자 : 문자열화 연산자] 

형식 

#define string(a) #a 

string(주라기 공원) 

//"주라기 공원"으로 문자열 상수화

쓰임 : 디버깅 코드에 주로 쓰인다. 

#define PRINT_VAR(x) printf(#x"=%d\n",x)

printf("i = %d\n", i);
PRINT_VAR(i); 

printf("j = %d\n", j); 
PRINT_VAR(j); 

//printf("j = %d\n", j)을 일일이 쓰기 힘들다면 문자열화 매크로를 사용

인자 생략 

#define print_age(x) printf(#x"x : %d", r); 

//c99부터는 인자 생략을 허용 
print_age();
//위 호출문은 아래와 같이 바뀐다. 
printf(" " ": %d\n ", r);

헤더 파일 

- .h 파일 

ex) 1.h, stdio.h , stdlib.h 

-#include , 매크로 정의, 함수 원형(선언), 기호 상수 등이 해당 헤더 파일 안에 정의 되어 있음 

-시스템이 제공하는 헤더 파일(표준 헤더 파일) 

-stdio.h, stdlib.h , string.h 등 

 

-사용자도 자신의 헤더 파일을 만들 수 있다. 

: 사용자 헤더 파일은 소스 파일과 같은 디렉터리에 생성한다. 

 

-#include를 통해 프로그램에 삽입한다. 

 

#include 

- 뒤에 명시된 파일을 #include 문장 대신에 삽입한다. 

-어떤 종류의 파일도 명시해도 되지만, 보통 헤더 파일(*.h)을 명시한다. 

-파일을 명시하는 두 가지 방법 

#include <filename> 

- 표준 헤더 파일을 삽입할 때 사용한다. 

- 시스템이 정의한 디렉토리에서 filename 파일을 찾아 삽입한다. 

- 일반적으로 , 표준 헤더 파일이 저장된 장소는 시스템에 따라 다르다. 

 

# include "filename"

- 사용자 헤더 파일을 삽입할 대 사용한다. 

- 먼저 현재 디렉토리에서 검색하고, 거기에 없다면 시스템이 정의한 디렉토리에서 검색하여 삽입한다. 

 

//위 헤더 define이 중복된다면, 한꺼번에 pi.h 만들기 

#include <stdio.h>
#define PI 3.14 
#define CIRCUMFERENCE(x)	(2.0 * (x) * PI)
#define AREA(x)				((x)*(x)*PI)
#define VOLUME(x)			(4.0/3.0 *(x) *(x) *(x) * PI)
#define SURFACE_AREA(x)		(4.0 * (x) *(x)*PI)

 

//만들어둔 pi.h를 포함
#include "pi.h"

int main(void) {
	double r; 
	printf("반지름을 입력하세요: "); 
	scanf("%lf", &r); 
	printf("반지름이 %.3f인 \n", r); 
	printf("원의 원둘레 길이 : %.3f\n", CIRCUMFERENCE(r));
	printf("원의 면적: %.3f\n", AREA(r)); 
	printf("구의 부피: %.3f\n", VOLUME(r)); 
	printf("구의 표면적: %.3f\n", SURFACE_AREA(r)); 
	return 0; 
}

'c언어' 카테고리의 다른 글

[C언어] 사용자 정의형 - 구조체  (0) 2022.10.24
[C언어] 비트 수준 접근  (0) 2022.10.23
[C언어] 공용체(union) / 열거형  (0) 2022.10.12
[C언어] 동적 메모리 할당  (0) 2022.09.07
[C언어] 포인터와 배열  (0) 2022.09.07