32
© 2012 생생생생생 All rights reserved 쉽쉽 쉽쉽쉽 C 쉽쉽 Express C Express 생 15 생 생생생 생 생생 생생

쉽게 풀어쓴 C 언어 Express

Embed Size (px)

DESCRIPTION

쉽게 풀어쓴 C 언어 Express. 제 15 장 전처리 및 비트 필드. C Express. 이번 장에서 학습할 내용. 전처리와 기타 중요한 테마에 대하여 학습한다. 전처리 지시자 다중 소스 프로그램 비트 필드. 전처리기란 ?. 전처리기 (preprocessor ) : 컴파일에 앞서 소스 파일을 처리. 수고했어 , 나머지는 나한테 맡겨 !. #include, #define 등을 처리 합니다. 소스 파일. 임시 파일. 오브젝트 파일. 컴파일 러. 전처리기. 단순 매크로. - PowerPoint PPT Presentation

Citation preview

© 2012 생능출판사 All rights reserved

쉽게 풀어쓴 C 언어 Express쉽게 풀어쓴 C 언어 Express

C Express제 15 장 전처리 및 비트 필드

© 2012 생능출판사 All rights reserved

이번 장에서 학습할 내용

• 전처리 지시자• 다중 소스 프로그램• 비트 필드

전처리와 기타 중요한 테마에

대하여 학습한다 .

© 2012 생능출판사 All rights reserved

전처리기란 ?· 전처리기 (preprocessor): 컴파일에 앞서 소스 파일을 처리

소스파일

임시파일

오브젝트 파일

#include, #define 등을 처리 합니다 .

수고했어 ,나머지는

나한테 맡겨 !

전처리기 컴파일러

© 2012 생능출판사 All rights reserved

단순 매크로· 단순 매크로 (macro): 기호 상수 정의

#define SIZE 100#define PI 3.141592

사람은 숫자보다기호를 잘 기억하므로 3.141592보다는 PI 가 낫죠 !

전처리기

while (i < SIZE){ sum += i; i++;}

while (i < 100){ sum += i; i++;}

#define SIZE 100

© 2012 생능출판사 All rights reserved

단순 매크로의 장점· 프로그램의 가독성 향상· 상수 변경이 용이

기호 상수를 사용하는 경우 :정의된 부분만 수정하면 됨

리터럴을 사용하는 경우 :모든 곳을 수정해야 함

© 2012 생능출판사 All rights reserved

단순 매크로의 예#define SIZE 100 // 배열 크기#define MAX_INT 2147483647 // 최대정수#define PI 3.141592 // 원주율#define TWOPI (3.141592 * 2.0) // 원주율의 2 배#define EOF (-1) // 파일의 끝 표시#define DIGITS "0123456789" // 문자 상수 정의#define BRACKET "(){}[]" // 문자 상수 정의

#define MAX_LEN 100 // 문자열 최대 길이#define MAX_SIZE (MAX_LEN + 1) // 문자 배열 최대 크기

#define EXPR x = y + 1; p = "abc" // 어떤 형태라도 정의 가능

© 2012 생능출판사 All rights reserved

함수형 매크로· 함수형 매크로 : 함수처럼 인자를 가질 수 있는 매크로

· #define SQUARE(x) ((x) * (x))

v = SQUARE(3);

v = ((3) * (3));

#define SUM(x, y) ( (x) + (y) )#define AVERAGE(x, y, z) ( ( (x) + (y) + (z) ) / 3 )#define MAX(x, y) ( (x) > (y) ) ? (x) : (y) )#define ABS(x) ( (x) < 0 ) ? -(x) : (x) )

#define getchar() getc(stdin)#define putchar(c) putc((c), stdout)

© 2012 생능출판사 All rights reserved

주의할 점#define SQUARE(x) x * x // 위험 !!v = SQUARE(1 + 2);// v = 1 + 2 * 1 + 2; 1 + 2 + 2 5 (≠ 9)

#define SQUARE(x) (x) * (x) // 위험 !!v = SQUARE(1 + 2);// v = (1 + 2) * (1 + 2); 3 * 3 9v = 20 / SQUARE(2);// v = 20 / (2) * (2); 10 * 2 20 (≠ 5)

#define SQUARE(x) ((x) * (x)) // 최대한 안전한 형태v = SQUARE(1 + 2);// v = ((1 + 2) * (1 + 2)); (3 * 3) 9v = 20 / SQUARE(2);// v = 20 / ((2) * (2)); 20 / 4 5

함수형 매크로에서는 인자와 전체를 괄호로 둘러싸는 것이 안전합니다 .

© 2012 생능출판사 All rights reserved

함수형 매크로의 장단점· 함수 호출보다 실행 속도가 빠름 · 큰 매크로를 많이 사용하면 실행 프로그램 크기 증가· 디버깅이 어려움· 함수에 비해 위험

#define SQUARE(x) ((x) * (x))

n = 1;v = SQUARE(++n);// v = ((++n) * (++n));// n = 3, v = 9 or 6

int square(int x) { return x * x; }

n = 1;v = square(++n);// n = 2, v = 4

© 2012 생능출판사 All rights reserved

예제#include <stdio.h>

#define SQUARE(x) ((x) * (x)) int main(void) {

int x = 2;

printf("%d\n", SQUARE(x));printf("%d\n", SQUARE(3));printf("%f\n", SQUARE(1.2));

printf("%d\n", SQUARE(x+3));printf("%d\n", 100/SQUARE(x));printf("%d\n", SQUARE(++x)); // 논리 오류

return 0;

}

491.440000252516

© 2012 생능출판사 All rights reserved

매크로 정의 해제· #undef 매크로 : 매크로에 대한 정의 취소 (undefine)

· 긴 매크로 처리 방법 : 한 줄 이상이면 반드시 끝에 연속 마크 (\) 사용

#define OUT_ERROR(code, message) \printf("[%d] %s\n", \

(code), (message))

#define SIZE 10 …#undef SIZEint SIZE;

© 2012 생능출판사 All rights reserved

매크로 연산자· # 연산자 : 매크로 인자를 문자열로 변환 ( 전위 단항 연산자 )

#define PRINT(exp) printf(#exp " = %d\n", (exp))x = 1;PRINT(x + 2);// printf("x + 2" " = %d\n", x + 2);// printf("x + 2 = %d\n", x + 2);// x + 2 = 3

· ## 연산자 : 하나의 토큰으로 병합 ( 이항 연산자 )

#define VAR(n) v##n#define TOKEN(name, n) name ## n VAR(1) = 2;// v1 = 2;s = TOKEN(sum, 2);// s = sum2;

© 2012 생능출판사 All rights reserved

예제 #include <stdio.h>

#define MAKE_NAME(n) v ## n#define PRINT(n) printf("v" #n " = %d\n", MAKE_NAME(n));

int main(void) {int MAKE_NAME(1) = 10; // int v1 = 10; int MAKE_NAME(2) = 20; // int v2 = 20;PRINT(1); // printf("v1 = %d\n", v1);PRINT(2); // printf("v2 = %d\n", v2);return 0;

}

v1 = 10v2 = 20

© 2012 생능출판사 All rights reserved

내장 매크로· 내장 매크로 : 미리 정의된 매크로

매크로 값

__DATE__ 컴파일 날짜 ( 문자열 )

__TIME__ 컴파일 시간 ( 문자열 )

__FILE__ 소스 파일 이름 ( 문자열 )

__LINE__ 현재 라인 번호 ( 정수 )printf(" 컴파일 시간 = %s %s\n", __DATE__, __TIME__);// 컴파일 시간 = Oct 9 2012 13:03:04

printf(" 에러 발생 : 파일 이름 = %s, 라인 번호 = %d\n", __FILE__, __LINE__);

© 2012 생능출판사 All rights reserved

예제 : ASSERT 매크로#include <stdio.h>#include <stdlib.h>

#define ASSERT(exp) \ if (!(exp)) \

printf("[%s %d] 조건 실패 : " #exp "\n", __FILE__, __LINE__), exit(1)

int main(void) {int sum;ASSERT(sum == 0);

return 0;}

[assert.c 10] 조건 실패 : sum == 0

© 2012 생능출판사 All rights reserved

비트 조작 매크로· #define BIT_GET(w, k) (((w) >> (k)) & 0x01)

· w 에서 k 번째 비트 값 획득· 결과 : 0 / 1

· #define BIT_SET (w, k) ((w) | 0x01 << (k))· w 의 k 번째 비트를 1 로 설정

· #define BIT_RESET(w, k) ((w) & ~(0x01 << (k)))· w 의 k 번째 비트를 0 로 설정

© 2012 생능출판사 All rights reserved

예제 : 비트 조작 매크로#include <stdio.h>

#define BIT_GET(w, k) (((w) >> (k)) & 0x01)#define BIT_SET(w, k) ((w) | 0x01 << (k))#define BIT_RESET(w, k) ((w) & ~(0x01 << (k)))

int main(void) {int data = 0;

data = BIT_SET(data, 2);printf("%08X %d\n", data, BIT_GET(data, 2));

data = BIT_RESET(data, 2);printf("%08X %d\n", data, BIT_GET(data, 2));

return 0;}

00000004 100000000 0

© 2012 생능출판사 All rights reserved

조건부 컴파일 지시자· #if 조건 : 조건이 참이면

· 조건 : 정수 상수 조건이어야 하고 논리 , 관계 연산자 등 허용· #ifdef 매크로 : 매크로가 정의되어 있으면

· #ifdef M #if defined(M)· defined(M): 전처리 연산자 , 매크로 M 이 정의되어 있으면 참

· #ifndef 매크로 : 매크로가 정의되어 있지 않으면· #ifndef M #if !defined(M)

· #else: 그렇지 않으면· #elif 조건 : 그렇지 않고 조건이 참이면 (else if)· #endif: 조건부 컴파일 지시자 끝

· #if / #ifdef / #ifndef …#endif

© 2012 생능출판사 All rights reserved

조건부 컴파일 지시자 예#ifdef LINUX ... // LINUX 버전인 경우#else ... // LINUX 버전이 아닌 경우#endif

#ifndef LIMIT // LIMIT 이 정의되어 있지 않으면# define LIMIT 1000#endif

#if DEBUG_LEVEL >= 1 printf("result = %d\n", result);#endif

#if NATION == 1#include "korea.h"

#elif NATION == 2#include "china.h"

#else #include "usa.h"

#endif

#if 0 // 전처리 기능을 이용한 주석 처리 … …#endif

© 2012 생능출판사 All rights reserved

예제#include <stdio.h>#define DELUXE

int main(void) {

#ifdef DELUXEprintf(" 딜럭스 버전입니다 .\n");

#endif

return 0;}

딜럭스 버전입니다 .

© 2012 생능출판사 All rights reserved

조건부 컴파일 지시자· #if VERSION > 3 // 가능 ! 버전이 3 보다 크면

· #if (AUTHOR == KIM) // 가능 ! KIM 은 매크로

· #if (VERSION * 10 > 500 && LEVEL == BASIC) // 가능 !

· #if (VERSION > 3.0) // 오류 ! 실수는 허용되지 않음 · #if (AUTHOR == "CHULSOO") // 오류 ! 문자열은 허용되지 않음

· #if (VERSION > 300 || defined(DELUXE)) // 가능 !

© 2012 생능출판사 All rights reserved

#include· #include <…>

· 표준 디렉토리 ( 폴더 ) 에서 파일 탐색· #include "…"

· 현재 디렉토리에서 파일 탐색 표준 디렉토리에서 파일 탐색 ( 현재 디렉토리에 없는 경우 )

· 경로 지정 가능· #include "graphic/point.h" · #include "D:\Project\source\point.h"· #include "/home/user1/source/point.h"

© 2012 생능출판사 All rights reserved

헤더 파일 중복 포함 방지

// main.c#include <stdio.h>#include "rect.h"#include "shape.h"…

// rect.hstruct rect { int x, y, w, h; };…

// rect.h#ifndef RECT_H#define RECT_Hstruct rect { int x, y, w, h; };…#endif

// shape.h#include "rect.h"…

// shape.h#ifndef SHAPE_H#define SHAPE_H#include "rect.h"…#endif

© 2012 생능출판사 All rights reserved

다중 소스 파일· 단일 소스 파일

· 소스의 재사용과 관리가 어려움· 일부만 수정한 경우에도

전체를 다시 컴파일해야 함

· 다중 소스 파일· 모듈별로 별도의 소스 파일 유지

소스의 재사용과 관리가 용이함· 변경된 소스 파일만 다시 컴파일

컴파일 시간 단축

© 2012 생능출판사 All rights reserved

다중 소스 파일

라이브러리

© 2012 생능출판사 All rights reserved

예제#include <stdio.h>#include "power.h"

int main(void) {int x,y;

printf("x 의 값을 입력하시오 : ");scanf("%d", &x);printf("y 의 값을 입력하시오 : ");scanf("%d", &y);printf("%d 의 %d 제곱값은 %f\n", x, y,

power(x, y));

return 0;}

#include "power.h"

double power(int x, int y) {

double result = 1.0;int i;for (i = 0;i < y; i++)

result *= x;return result;

}

#ifndef POWER_H#define POWER_H

double power(int x, int y);

#endif

main.cpower.h

power.c

x 의 값을 입력하시오 : 2y 의 값을 입력하시오 : 32 의 3 제곱값은 8.000000

© 2012 생능출판사 All rights reserved

헤더 파일을 사용하지 않으면함수 원형 선언 반복

© 2012 생능출판사 All rights reserved

헤더 파일을 사용하면

헤더 파일 포함

© 2012 생능출판사 All rights reserved

다중 소스 파일에서 외부 변수

© 2012 생능출판사 All rights reserved

비트 필드· int/unsigned 타입의 구조체 필드는 비트 단위로 크기 지정 가능

비트 필드· 메모리 절약

struct product { unsigned style : 1; //

[0, 1] unsigned size : 2; // [0, 3]int value : 5; // [-16,

+15]};

int/unsigned (word)

value sizestyle

© 2012 생능출판사 All rights reserved

예제#include <stdio.h> struct product {

unsigned style : 1; unsigned size : 2; int value : 5;

}; int main(void) {

struct product p;

p.style = 1;p.size = 2;p.value = -10;

printf("style = %u, size = %u, value = %d\n", p.style, p.size, p.-

value);printf("sizeof p = %d\n", sizeof p);printf("p = %08X\n", p);

return 0;

}

style = 1, size = 2, value = -10sizeof p = 4p = 000000B5

value sizestyle

? … ? 1 0 1 1 0 1 0 1

© 2012 생능출판사 All rights reserved

비트 필드struct product {

int code; // 일반 멤버unsigned style : 1; unsigned : 3; // 자리만 차지unsigned size : 2; int value : 5; unsigned : 0; // 현재 워드의 나머지 비트는 사용하지

않음unsigned state : 4; // 다음 워드에 할당

};

value size style

code

state