1 / 32

쉽게 풀어쓴 C 언어 Express

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

Download Presentation

쉽게 풀어쓴 C 언어 Express

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 쉽게 풀어쓴 C언어 Express 제15장 전처리 및 비트 필드 C Express

  2. 이번 장에서 학습할 내용 전처리와 기타 중요한 테마에 대하여 학습한다. • 전처리 지시자 • 다중 소스 프로그램 • 비트 필드

  3. 전처리기란? • 전처리기(preprocessor): 컴파일에 앞서 소스 파일을 처리 수고했어, 나머지는 나한테 맡겨! #include, #define 등을 처리 합니다. 소스 파일 임시 파일 오브젝트 파일 컴파일러 전처리기

  4. 단순 매크로 사람은 숫자보다기호를 잘 기억하므로 3.141592보다는 PI가 낫죠! • 단순 매크로(macro): 기호 상수 정의 #define SIZE 100 #define PI 3.141592 #define SIZE 100 while (i < SIZE) { sum += i; i++; } while (i < 100) { sum += i; i++; } 전처리기

  5. 단순 매크로의 장점 • 프로그램의 가독성향상 • 상수 변경이 용이 리터럴을사용하는 경우: 모든 곳을 수정해야 함 기호 상수를 사용하는 경우: 정의된 부분만 수정하면 됨

  6. 단순 매크로의 예 #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"// 어떤 형태라도 정의 가능

  7. 함수형 매크로 • 함수형 매크로: 함수처럼 인자를 가질 수 있는 매크로 • #define SQUARE(x) ((x) * (x)) #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) v = SQUARE(3); v = ((3) * (3));

  8. 주의할 점 #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  9 v = 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)  9 v = 20 / SQUARE(2); // v = 20 / ((2) * (2));  20 / 4  5 함수형 매크로에서는 인자와 전체를 괄호로 둘러싸는 것이 안전합니다.

  9. 함수형 매크로의 장단점 • 함수 호출보다 실행 속도가 빠름 • 큰 매크로를 많이 사용하면 실행 프로그램 크기 증가 • 디버깅이 어려움 • 함수에 비해 위험 #define SQUARE(x) ((x) * (x)) n = 1; v = SQUARE(++n); //  v = ((++n) * (++n)); // n = 3, v = 9 or 6 intsquare(int x) { return x * x; } n = 1; v = square(++n); // n = 2, v = 4

  10. 예제 #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; } 4 9 1.440000 25 25 16

  11. 매크로 정의 해제 • #undef매크로:매크로에대한 정의 취소(undefine) • #define SIZE 10 • … • #undefSIZE • intSIZE; • 긴 매크로 처리 방법: 한 줄 이상이면 반드시 끝에 연속 마크(\) 사용 #define OUT_ERROR(code, message) \ printf("[%d] %s\n", \ (code), (message))

  12. 매크로 연산자 • #연산자: 매크로 인자를 문자열로 변환 (전위 단항 연산자) #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;

  13. 예제 #include<stdio.h> #define MAKE_NAME(n) v ## n #define PRINT(n) printf("v" #n " = %d\n", MAKE_NAME(n)); intmain(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 = 10 v2 = 20

  14. 내장 매크로 • 내장 매크로: 미리 정의된 매크로 printf("컴파일 시간 = %s %s\n", __DATE__, __TIME__); // 컴파일 시간 = Oct 9 2012 13:03:04 printf("에러 발생: 파일 이름 = %s, 라인 번호 = %d\n", __FILE__, __LINE__);

  15. 예제: 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

  16. 비트 조작 매크로 • #defineBIT_GET(w, k) (((w) >> (k)) & 0x01) • w에서 k번째 비트 값획득 • 결과: 0 / 1 • #defineBIT_SET (w, k) ((w) | 0x01 << (k)) • w의 k번째 비트를1로 설정 • #defineBIT_RESET(w, k) ((w) & ~(0x01 << (k))) • w의 k번째 비트를0로 설정

  17. 예제: 비트 조작 매크로 #include<stdio.h> #defineBIT_GET(w, k) (((w) >> (k)) & 0x01) #defineBIT_SET(w, k) ((w) | 0x01 << (k)) #defineBIT_RESET(w, k) ((w) & ~(0x01 << (k))) int main(void) { intdata = 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 1 00000000 0

  18. 조건부 컴파일 지시자 • #if조건: 조건이 참이면 • 조건: 정수 상수 조건이어야 하고 논리, 관계 연산자 등 허용 • #ifdef매크로: 매크로가 정의되어 있으면 • #ifdefM  #ifdefined(M) • defined(M): 전처리 연산자, 매크로 M이 정의되어 있으면 참 • #ifndef매크로: 매크로가 정의되어 있지 않으면 • #ifndefM  #if!defined(M) • #else: 그렇지 않으면 • #elif조건: 그렇지 않고 조건이 참이면 (else if) • #endif: 조건부 컴파일 지시자 끝 • #if / #ifdef/ #ifndef …#endif

  19. 조건부 컴파일 지시자 예 #if DEBUG_LEVEL >= 1 printf("result = %d\n", result); #endif #ifdefLINUX ... // LINUX 버전인 경우 #else ... // LINUX 버전이아닌 경우 #endif #if NATION == 1 #include"korea.h" #elif NATION == 2 #include"china.h" #else #include"usa.h" #endif #ifndef LIMIT // LIMIT이 정의되어 있지 않으면 # define LIMIT 1000 #endif #if 0 // 전처리 기능을 이용한 주석 처리 … … #endif

  20. 예제 #include<stdio.h> #defineDELUXE int main(void) { #ifdef DELUXE printf("딜럭스 버전입니다.\n"); #endif return0; } 딜럭스 버전입니다.

  21. 조건부 컴파일 지시자 • #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))// 가능!

  22. #include • #include <…> • 표준디렉토리(폴더)에서 파일 탐색 • #include "…" • 현재 디렉토리에서 파일 탐색 표준디렉토리에서 파일 탐색 (현재 디렉토리에 없는 경우) • 경로 지정 가능 • #include "graphic/point.h" • #include "D:\Project\source\point.h" • #include "/home/user1/source/point.h"

  23. 헤더 파일 중복 포함 방지 // rect.h #ifndef RECT_H #define RECT_H structrect{ intx, y, w, h; }; … #endif // rect.h structrect{ intx, y, w, h; }; … // shape.h #include"rect.h" … // shape.h #ifndef SHAPE_H #define SHAPE_H #include"rect.h" … #endif // main.c #include<stdio.h> #include"rect.h" #include"shape.h" …

  24. 다중 소스 파일 • 단일 소스 파일 • 소스의 재사용과 관리가 어려움 • 일부만 수정한 경우에도전체를 다시 컴파일해야 함 • 다중 소스 파일 • 모듈별로 별도의 소스 파일 유지 소스의 재사용과 관리가 용이함 • 변경된 소스 파일만 다시 컴파일 컴파일 시간 단축

  25. 다중 소스 파일 라이브러리

  26. 예제 power.h main.c #ifndef POWER_H #define POWER_H doublepower(int x, int y); #endif #include<stdio.h> #include"power.h" int main(void) { intx,y; printf("x의값을입력하시오: "); scanf("%d", &x); printf("y의값을입력하시오: "); scanf("%d", &y); printf("%d의 %d 제곱값은 %f\n", x, y, power(x, y)); return 0; } power.c #include"power.h" double power(int x, int y) { double result = 1.0; inti; for (i = 0;i < y; i++) result *= x; return result; } x의 값을 입력하시오: 2 y의 값을 입력하시오: 3 2의 3 제곱값은8.000000

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

  28. 헤더 파일을 사용하면 헤더 파일 포함

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

  30. 비트 필드 • int/unsigned타입의 구조체필드는 비트 단위로 크기 지정 가능 비트 필드 • 메모리 절약 struct product { unsigned style : 1; // [0, 1] unsigned size : 2; // [0, 3] int value : 5; // [-16, +15] }; int/unsigned (word) value size style

  31. 예제 #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", sizeofp); printf("p = %08X\n", p); return 0; } value size style style = 1, size = 2, value = -10 sizeof p = 4 p = 000000B5

  32. 비트 필드 struct product { intcode;// 일반 멤버 unsigned style : 1; unsigned : 3; // 자리만 차지 unsigned size : 2; int value : 5; unsigned : 0; // 현재 워드의 나머지 비트는 사용하지 않음 unsigned state : 4; // 다음 워드에할당 }; value size style state

More Related