Download presentation
Presentation is loading. Please wait.
Published byHartanti Hadiman Modified 6년 전
1
Chapter 8 – 형 정의, 구조형 및 공용형 Outline 8.1 형 정의 typedef 8.2 구조형 struct
8.3 구조형과 함수 8.4 공용형 union 8.5 비트 필드 8.6 요약 8.7 예제
2
8.1 형 정의 typedef (예 8.1) typedef 정의와 선언 (예 8.1) typedef
/* (1) 정의 */ typedef int BOOL; typedef unsigned char TEXT; typedef int INCHES, FEET, YARDS; typedef int vector[10]; typedef char *string; /* (2) 선언 */ BOOL flag; /* int flag; 와 같은 의미 */ TEXT buf[100]; /* unsigned char buf[100];와 같은 의미 */ INCHES length, width; /* int length, width;와 같은 의미 */ vector a, b; /* int a[10], b[10];과 같은 의미 */ string text, input; /* char *text, *input;과 같은 의미 */ <typedef와 #define의 차이점> - typedef는 자료형에 대해서만 기호 이름을 부여 할 수 있다. - typedef는 전처리기가 아닌 컴파일러에 의해 실행된다.
3
8.1 형 정의 typedef (예 8.2) typedef의 사용(1) (예 8.2) typedef의 사용
/* (1) 정의 */ #define N 3 /* 벡터(vector)와 행렬(matrix)의 크기 */ typedef double scalar; typedef scalar vector[N]; typedef scalar matrix[N][N]; void add(a, b, c) vector a, b, c; /* double a[3], b[3], c[3];과 같은 의미 */ { int i; for (i = 0; i < N; i++) a[i] = b[i] + c[i]; } 함수 add()는 벡터를 연산하는 함수이다. matrix의 선언은 기 정의된 vector를 사용하면 다음과 같이도 할 수 있다. typedef vector matrix[N];
4
8.1 형 정의 typedef (예 8.3) typedef의 사용(2) (예 8.3) typedef의 사용
scalar dot_product(a, b) /* 벡터 a와 벡터 b의 내적(dot product) */ vector a, b; { int i; scalar s = 0; for (i = 0; i < N; i++) s += a[i] * b[i]; return s; } void multiply(a, b, c) /* 행렬 곱셈: a = b*c */ matrix a, b, c; int i, j, k; for (j = 0; j < N; j++) for (c[i][j] = 0, k = 0; k < N; k++) c[i][j] += a[i][k] * b[k][j]; 벡터의 내적 구하는 dot_product와 두 행렬의 곱을 계산하는 multiply scalar, vector의 정의는 예8.2에서 정의 matrix a, b, c;는 double a[N][N], b[N][N], c[N][N];과 동일.
5
8.2 구조형 struct 구조형 struct의 형식 태그명은 식별자이다. 태그명은 구조형의 template 명이라고도 한다.
(1) 새로운 구조형의 정의 (2) 이미 정의된 struct 태그명 형의 변수를 선언 (3) 새로운 구조형을 정의하고, 해당 변수도 선언함 struct 태그명 {항목_선언_리스트}; struct 태그명 식별자명 [, 식별자명 …]; (3) struct [태그명] {항목_선언_리스트} 식별자명 [, 식별자명 …]; 태그명은 식별자이다. 태그명은 구조형의 template 명이라고도 한다. [ ]안의 것은 생략 가능하다는 의미임.
6
8.2 구조형 struct (예 8.4) 구조형 struct 예(1)
형식3을 이용하여 태그명이 tg인 struct를 정의하고, struct tg형의 변수 y를 선언한다. struct tg에는 4개의 멤버가 있다. struct tg { short a; int b; char c; char d[4]; } y; (예 8.4) struct 예 형식 2를 이용하여 struct tg형의 변수 w, x, z를 추가로 선언한다. struct tg w, x, z;
7
8.2 구조형 struct (예 8.5) 구조형 struct 예(2)
(1)은 3학생의 레코드를 표현하기 위해 s1, s2, s3를 구조형 변수로 선언하고 있으나, 구조체의 태그명이 없으므로 다른 곳에서 추가적인 학생 레코드의 선언이 가능하지 않다. /* (1) */ struct { long student_id; /* 학번 */ char *student_name; /* 학생 이름 */ char grade; /* 성적 */ } s1, s2, s3; (예 8.5) struct 예
8
8.2 구조형 struct (예 8.5) 구조형 struct 예(2)
(2)에서는 구조체의 태그명으로 student를 사용하였으나, 변수 선언은 없다. (3)과 같이 하면, 비로소 변수들을 위한 기억장소가 할당된다. (예 8.5) struct 예 /* (2) */ struct student { long student_id; /* 학번 */ char *student_name; /* 학생 이름 */ char grade; /* 성적 */ }; /* (3) */ struct student temp, class[100]; (2)(3)을 결합시켜 다음과 같이 사용할 수 있다. struct student { long student_id; /* 학번 */ char *student_name; /* 학생 이름 */ char grade; /* 성적 */ } temp, class[100];
9
8.2 구조형 struct (예 8.6) typedef로 구조형 선언 다음의 변수 c는 구조형 배열이다.
complex를 struct 구문 대신 사용할 수 있다. (예 8.6) typedef로 구조형 선언 typedef struct { float re; /* 실수부 */ float im; /* 허수부 */ } complex; complex a, b, c[100];
10
8.2 구조형 struct (예 8.6 계속) typedef로 구조형 선언 [기억 장소 할당 형태] (예 8.6 계속)
11
8.2 구조형 struct 구조형 원소의 접근 (예 8.7) 구조형 멤버의 접근
구조형_변수명.멤버명 (예 8.7) 구조형 멤버의 접근 예8.4, 8.5, 8.6의 구조형 멤버에 대한 값 배정 구조형 배열의 각 원소의 멤버 접근 법: c[4].im 멤버 자체가 배열형 자료인 경우: y.d[0] (예 8.7) 구조형 멤버의 접근 y.a = 1; y.b = ; y.c = ‘A’; y.d[0] = ‘T’; y.d[1] = ‘A’; y.d[2] = ‘N’; y.d[3] = ‘K’; temp.grade = ‘A’; temp.student_name = “Chanho Park”; temp.student_id = 90118; c[0].re = 12.06; c[0].im = 3.0; c[4].re = 18.09;
12
8.2 구조형 struct (예 8.8) 구조형 멤버를 접근하는 프로그램
class가 구조형 배열이다. 즉 class의 각 원소는 구조형이다. 각 구조형 원소의 멤버 grade가 ‘F’면 cnt를 증가시킨다. /* F 학점 받은 학생수를 반환하는 함수 */ int fail_count(struct student class[]) { int i, cnt = 0; for (i = 0; i < NOSTUDENTS; i++) cnt += class[i].grade == ‘F’; return cnt; } (예 8.8) 구조형 멤버를 접근하는 프로그램
13
8.2 구조형 struct (예 8.9) 구조형의 내포와 참조
구조형 변수 x의 멤버 z가 구조형이므로 x.z.s같이 참조(즉 접근)한다. struct tgy { char cbuf[10]; struct tgz { int i; short s; } z; int t; } x; . . . x.z.s = 1; (예 8.9) 구조형의 내포와 참조
14
8.2 구조형 struct (예 8.10) 구조형의 초기화 구조형의 멤버보다 작은 수의 값이 할당되면 나머지는 0으로 간주된다. /* (1) */ complex m[3][3] = { {{1.0, -0.5}, {2.3, 1.0}, {0.7, 0.7} }, /* m[0][] 부분 */ {{7.0, -6.5}, {-0.5, 1.0}, {45.7, 8.0} }, /* m[1][] 부분 */ } /* m[2][]은 생략되었으므로 0으로 배정됨 */ /* (2) */ static struct month { char *mname; int day; } month_tab[] = { “January”, 31, “February”, 28, “March”, 31, “April”, 30, “May”, 31, “June”, 30, “July”, 31, “August”, 31, “September”, 30, “October”, 31, “November”, 30, “December”, 31 }; (예 8.10) 구조형의 초기화
15
8.2 구조형 struct (예 8.10 계속) 구조형의 초기화 (2)는 다음과 동일하다. (예 8.10 계속)
/* (2)’ */ static struct month { char *mname; int day; } month_tab[] = { {“January”, 31}, {“February”, 28}, {“March”, 31}, {“April”, 30}, {“May”, 31}, {“June”, 30}, {“July”, 31}, {“August”, 31}, {“September”, 30}, {“October”, 31}, {“November”, 30}, {“December”, 31} }; (예 8.10 계속) 구조형의 초기화
16
8.2 구조형 struct struct 형에 대한 포인터 구조형 포인터가 구조형 보다 다루기 편리한 경우 있음
구조형 포인터를 인수로 사용 구조형을 전달할 수 없는 C 컴파일러도 있다. 포인터를 넘기면 구조형의 복사가 일어나지 않아 메모리를 절약 구조형의 멤버로 다른 구조형을 가리키는 포인터를 사용하면 편리하다. (예 8.11) struct 형에 대한 포인터 선언 (예 8.11) 구조형의 포인터 /* (예 8.11) */ struct e { int n; int k; double s; }; /* struct e형의 배열 a[]를 선언하고 초기화 */ static struct e a[] = { {1, 5, }, {2, 6, }, {3, 6, } }; struct e *p; /* (1) */ p = a;
17
8.2 구조형 struct (예 8.11 계속) struct 형에 대한 포인터 선언 struct e *p;
p를 struct e 포인터 변수로 선언한다. p = a; 배열 a의 주소 즉 &a[0]를 p에 저장함 이제 p -> n으로 a[0].n을 접근할 수 있다. p++; 이제 p는 &a[1]과 같다. 이제 p -> n은 a[1].n과 같다. (예 8.11 계속) 구조형의 포인터
18
8.2 구조형 struct (예 8.12) 간접 멤버 연산자 -> 의 사용 예
구조형 포인터 변수 p에 구조형 변수 temp의 포인터를 배정하여 사용하고 있다. p -> grade는 p가 가리키는 구조형의 멤버 grade를 뜻함. /* (예 8.12) */ struct student temp, *p = &temp; temp.grade = ‘A’; temp.student_name = “Chanho Park”; temp.student_id = 90118; (예 8.12) -> 의 사용 수 식 연산 우선 순위 결 과 temp.student_name temp.grade temp.student_id (*p) -> student_name+2 *p -> student_name+2 *(p -> student_name+2) p -> student_name p -> grade p -> student_id *((*p) -> student_name) + 2 *(p -> student_name) + 2 p -> student_name [2] Chanho Park A 90118 /* 에러 */ E a
19
8.3 구조형과 함수 (예 8.13) 함수에 구조형 멤버 자료 전달
8.3 구조형과 함수 (예 8.13) 함수에 구조형 멤버 자료 전달 구조형 멤버를 인수로: 인수가 복사되어 call by value로 동작 구조형 멤버의 포인터를 인수로: 앞에 &를 붙여 주소를 넘김 : call by reference의 효과 주소 연산자 &는 멤버 앞이 아니라 구조형의 이름 앞에 쓴다. [주의] 문자열 s는 자체가 주소를 의미한다. /* (1) */ struct fred { char x; int y; char s[10]; } mike; /* (2) */ func1(mike.x); /* x의 문자값 전달 */ func2(&mike.x); /* 문자형 x의 주소 전달 */ func3(mike.y); /* y의 정수값 전달 */ func4(&mike.y); /* 정수형 y의 주소 전달 */ func5(mike.s); /* 문자열 s의 주소 전달 */ func6(mike.s[2]); /* s[2]의 문자값 전달 */ func7(&mike.s[2]); /* 문자형 s[2]의 주소 전달 */ (예 8.13) 함수에 구조형 멤버 자료 전달
20
8.3 구조형과 함수 (예 8.14) 함수에 구조형 전체를 전달(1) (예 8.14) 함수에 구조형 전체를 전달
8.3 구조형과 함수 (예 8.14) 함수에 구조형 전체를 전달(1) (예 8.14) 함수에 구조형 전체를 전달 /* File : prog8-14.c 함수에 구조형 전체를 전달(1) */ #include <stdio.h> int main(void) { struct { int a, b; char ch; } arg; void f1(); arg.a = 1000; f1(arg); 13 } 14
21
8.3 구조형과 함수 (예 8.14) 함수에 구조형 전체를 전달(1)
8.3 구조형과 함수 (예 8.14) 함수에 구조형 전체를 전달(1) 실 매개변수(arg)와 형식 매개 변수(parm)을 같은 구조형으로 선언. 인수 선언시 struct를 선언하는 방식으로 컴파일러에 따라 Warning 메시지를 주기도 함 (예 8.14 계속) 함수에 구조형 전체를 전달 output 15 void f1(parm) 16 struct { int x, y; char ch; 19 } parm; 20 { printf(“%d\n”, parm.x); 22 } 1000
22
8.3 구조형과 함수 (예 8.15) 함수에 구조형 전체를 전달(2) (예 8.14) 대신 이 방법을 사용하시오!!
8.3 구조형과 함수 (예 8.15) 함수에 구조형 전체를 전달(2) (예 8.14) 대신 이 방법을 사용하시오!! 동일한 struct형을 중복 선언하지 않는 버전 /* File : prog8-15.c 함수에 구조형 전체를 전달(2) */ #include <stdio.h> /* 구조형 형 정의 */ struct struct_type { int a, b; char ch; }; int main(void) 10 { struct struct_type arg; /* arg 선언 */ void f1(); arg.a = 1000; f1(arg); 15 } 16 void f1(parm) 17 struct struct_type parm; 18 { printf(“%d\n”, parm.a); 20 } (예 8.15) 함수에 구조형 전체를 전달
23
8.3 구조형과 함수 포인터 기반 함수와 구조형 기반 함수 다음 구조형을 정의하여 사용하자. 헤더 file complex.h
8.3 구조형과 함수 포인터 기반 함수와 구조형 기반 함수 다음 구조형을 정의하여 사용하자. 헤더 file complex.h /* File : complex.h For prog8-16.c & prog8-17.c */ typedef struct { float re; float im; } complex;
24
8.3 구조형과 함수 (예 8.16) 포인터 기반 함수(구조형 전달)의 선언과 호출
8.3 구조형과 함수 (예 8.16) 포인터 기반 함수(구조형 전달)의 선언과 호출 다음 3 개의 함수를 포인터 인수를 사용하여 구현하자. 복소수에 값을 배정하는 함수 두 개의 복소수를 더하는 함수 복소수를 출력하는 함수 /* File : prog8-16.c 포인터 기반 함수(구조형 전달)의 선언과 호출 */ #include <stdio.h> #include “complex.h” void assign(complex *cp, float r, float i) { cp->re = r; /* (2) */ cp->im = i; } 10 void add(complex *cp1, complex *cp2, complex *cp3) 11 { cp3->re = cp1->re + cp2->re; cp3->im = cp1->im + cp2->im; 14 } 15 16 (예 8.16) 포인터 기반 함수
25
8.3 구조형과 함수 (예 8.16 계속) (예 8.16 계속) output 17 void prnt(complex *cp)
8.3 구조형과 함수 (예 8.16 계속) 17 void prnt(complex *cp) 18 { printf(“%.3f + %.3f i\n”, cp->re, cp->im); 20 } 21 22 int main(void) 23 { complex c1, c2, c3; assign(&c1, 1.0, 2.0); assign(&c2, 3.0, 4.0); add(&c1, &c2, &c3); prnt(&c3); 28 } (예 8.16 계속) output i
26
8.3 구조형과 함수 (예 8.17) 구조형 자료를 인수 및 반환값으로 사용 이것이 가능하지 않은 C 컴파일러도 있음.
8.3 구조형과 함수 (예 8.17) 구조형 자료를 인수 및 반환값으로 사용 이것이 가능하지 않은 C 컴파일러도 있음. 구조형이 값 호출(call by value)로 복사(copy)되어 전달 다음은 (예8.16)의 add2는 add를 재 작성한 버젼이다. 계산 결과를 구조체(res)에 저장하고 반환값으로 사용하였다. main에서 호출하는 부분(줄26)도 바뀐다. (예 8.17) 구조형 자체를 인수와 반환값으로 사용 호출 부분의 변경 /* File : prog8-17.c 구조형을 인수와 반환값으로 사용하는 add2의 작성 */ 10 complex add2(complex c1, complex c2) 11 { complex res; /* 계산 결과를 저장 */ res.re = c1.re + c2.re; res.im = c1.im + c2.im; return res; 16 } c3 = add2(c1, c2);
27
8.4 공용형 union (예 8.18) 공용형 자료 정의 n은 int형이므로 통상 4바이트, x는 double 형이므로 통상 8바이트, c는 char형이므로 통상 1바이트가 필요함. union의 멤버들(n, x, c)은 기억장소를 공유한다. 따라서 멤버 중 가장 큰 메모리를 필요로 하는 멤버 x가 필요한 공간(8바이트)을 확보한다. 모든 멤버 중 단 한 개만 사용하는 경우(가령 심볼 테이블 등) 공간 절약을 위해 흔히 사용된다. (예 8.18) union /* (예 8.18) */ union ifc { int n; double x; char c; } temp;
28
8.4 공용형 union (예 8.19) 공용형 자료 정의 union과 struct의 차이점은 union의 멤버들은 모두 같은 주소에 배정된다는 점이다. union은 공간을 절약할 수 있다. union ifc의 3 멤버는 주소가 같으므로, 가령 temp.n에 저장 후, temp.x에 저장하면 temp.n의 원래 값은 엉뚱한 값이 됨. union 멤버의 접근 방법은 struct와 동일하다. (예 8.19) union 변수의 선언과 참조 /* (예 8.19) */ union ifc fit; union ifc save[10]; /* 10개의 공용형 변수 배열 */ union ifc *pu; /* union ifc형 자료에 대한 포인터 변수 temp.n = 444; /* (예 8.18)에서 정의된 변수 temp의 멤버값 배정 */ temp.x = 15.9; temp.c = ‘H’; fit.n = 23; fit.x = 2.0; fit.c = ‘a’; pu = &fit; k = pu -> n; /* k = fit.n과 같음 */
29
8.4 공용형 union (예 8.20) 구조형과 공용형의 혼용
union fromwhere은 foreign_traveller와 korean_traveller라는 멤버를 가진다. 이 두 멤버는 동시에 사용되지 않으므로 공용형 멤버로 정의되었다. (예 8.20) struct와 union의 혼용 /* (예 8.20) */ struct foreign_traveller { int country_code; int city_code; *pc; char passport_id[20]; }; struct korean_traveller { int district_code; char resident_id[13]; union fromwhere { struct foreign_traveller f_trav; struct korean_traveller k_trav;
30
8.4 공용형 union (예 8.20 계속) 구조형과 공용형의 혼용
traveller_record란 구조형의 한 멤버로 union fromwhere 형을 사용하고 있다. (예 8.20 계속) /* (예 8.20 계속) */ typedef struct { int serial_no; char name[10]; short iskorean; union fromwhere a; } traveller_record;
31
8.5 비트 필드 (예 8.21) 비트 필드(bit field)의 사용 1 또는 0의 값 만을 갖는 비트 단위로 정의 가능
8.5 비트 필드 (예 8.21) 비트 필드(bit field)의 사용 1 또는 0의 값 만을 갖는 비트 단위로 정의 가능 (1) (1/0 저장 가능한) 1비트짜리 멤버 3 개로 이루어진 struct (2) (문자 저장 가능한) 8비트짜리 멤버 4 개로 이루어진 struct /* (예 8.21) 비트 필드의 사용 */ /* (1) */ struct { unsigned class_a : 1; unsigned class_b : 1; } fig; /* (2) */ struct word_bytes { unsigned byte0 : 8, byte1 : 8, byte2 : 8, byte3 : 8; } y; (예 8.21) 비트 필드 선언 비트 필드의 접근 fig.class_a = 1; y.byte3 = ‘w’;
32
8.5 비트 필드 (예 8.22) 마스크 사용 비트 처리 시스템에 따라 비트 필드를 사용하면 효율이 떨어질 수 있다.
8.5 비트 필드 (예 8.22) 마스크 사용 비트 처리 시스템에 따라 비트 필드를 사용하면 효율이 떨어질 수 있다. 특정 비트의 마스크를 이용한 방법이 일반적인 방법임. 01, 02, 04와 같이 맨 앞에 0을 붙이면 8진법 숫자임. (1) 정수 fig의 0번째 비트를 1로 set시킴. (2) 정수 fig의 1번째 비트가 0인지 테스트 함 (fig & BIT1)은 fig의 해당 비트가 1이면 참(1), 0이면 거짓(0)임 (예 8.22) 마스크 사용 비트 처리 /* (예 8.22) 마스크 사용 비트 처리 */ #define BIT0 01 #define BIT1 02 #define BIT2 04 int fig; fig |= BIT0; /* (1) */ if ((fig & BIT1) == 0) /* (2) */
33
8.7 예제 예제 8.1 [해 설] (1) WHOLE은 int형과 동의어로 정의된다.
8.7 예제 /* 예제 8.1 다음 선언들의 의미는? */ /* (1) */ typedef int WHOLE; /* (2) */ typedef struct club { char name[30]; int size, year; } GROUP; /* (3) */ typedef GROUP, *PG; /* (4) */ typedef void DRAW(int, int); 예제 [해 설] (1) WHOLE은 int형과 동의어로 정의된다. (2) 3개의 멤버를 가진 struct club을 선언하고, GROUP를 그와 동의어로 정의한다. (3) PG는 기 정의된 GROUP 포인터 형라고 정의 된다. (4) 정수 2개를 인수로 취하고 반환형이 없는 함수에 대한 형 정의이다. DRAW box; 는 void box(int, int); 와 같은 선언이 된다.
34
(1) complex라는 구조형 변수를 정의함. 그 구조형은 float형 x, y를 멤버로 갖으나, 태그가 없다.
/* 예제 8.2 다음 선언들의 의미는? */ /* (1) */ struct { float x, y; } complex; /* (2) */ } complex[100]; /* (3) */ struct employee { char name[20] int id; long class; } temp; 예제 [해 설] (1) complex라는 구조형 변수를 정의함. 그 구조형은 float형 x, y를 멤버로 갖으나, 태그가 없다. (2) 구조형의 배열 선언. 각 원소는 2개의 멤버를 가진 구조형이다. (3) temp라는 구조형 변수 선언. 구조형의 멤버는 name, id, class이다.
35
(4) 변수 student, faculty, staff를 struct employee형으로 선언
/* 예제 8.2(계속) */ /* (4) */ struct employee student, faculty, staff; /* (5) */ struct sample { char c; float *pf; struct sample *next; } x; /* (6) */ struct { unsigned icon : 8; unsigned color : 4; unsigned underline : 1; unsigned blink : 1; } screen[25][80]; 예제 8.2(계속) [해 설] (4) 변수 student, faculty, staff를 struct employee형으로 선언 (5) 구조형의 3째 멤버 next는 동일한 구조형 자료에 대한 포인터이다. (6) screen이라는 이름의 구조형 배열로 원소는 2000개이다. 각 원소는 4개의 멤버로 구성되고, 각 멤버는 각각 길이가 8비트, 4비트, 1비트, 1비트이다.
36
(1) struct rec 형의 변수 item의 멤버 a에 10을 배정한다.
/* 예제 8.3 다음 문장들의 의미는? */ struct rec { int a; struct rec *sp; } item, list[5]; /* (1) */ item.a = 10; /* (2) */ list[0].sp = &list[1]; list[0].sp -> a = 20; /* (3) */ list[3].a = 30; 예제 [해 설] (1) struct rec 형의 변수 item의 멤버 a에 10을 배정한다. (2) 배열 list의 0번째 원소의 멤버 sp의 값으로 list[1]의 포인터를 저장. 이후 그 포인터가 가리키는 구조체(즉 list[1])의 멤버 a에 20을 저장. (3) 구조형의 배열로부터, 각 구조형 원소의 멤버에 접근하는 방법.
37
예제 8.4 1 /* File : ex8-4.c 2 복소수 계산 프로그램 */ 3 #include <stdio.h>
복소수 계산 프로그램 */ #include <stdio.h> #define CMPLX struct complex CMPLX { double re; double im; }; int main(void) 10 { static CMPLX za = {3.0, 4.0}; static CMPLX zb = {5.0, 6.0}; CMPLX z, cadd(), cmult(); void cprint(); z = cadd(za, zb); cprint(z); z = cmult(za, zb); cprint(z); 16 } /* 복소수 덧셈 */ 18 CMPLX cadd(CMPLX za, CMPLX zb) 19 { CMPLX z; z.re = za.re + zb.re; z.im = za.im + zb.im; return z; 24 } 예제 8.4
38
줄4로 CMPLX를 struct complex와 같게 선언함.
/* 복소수 곱셈 */ 26 CMPLX cmult(CMPLX za, CMPLX zb) 27 { CMPLX z; z.re = za.re * zb.re - za.im * zb.im; z.im = za.re * zb.im + za.im + zb.re; return z; 32 } /* 복소수 출력 */ 34 void cprint(CMPLX z) 35 { printf(“%.3f + %.3f i\n”, z.re, z.im); 37 } 예제 8.4(계 속) [해 설] output 줄4로 CMPLX를 struct complex와 같게 선언함. 복소수를 실수부 re(real)와 허수부 im(imaginary)로 구성된 구조형으로 정의. 두 복소수의 합과 곱을 구하는 프로그램 i i
39
struct의 멤버로 struct를 사용할 수 있다.
/* File : ex8-5.c struct와 내포된 struct */ #include <stdio.h> int main(void) { static struct s1 { char c[4], *s; } s1 = {“abc”, “def” }; static struct s2 { char *cp; struct s1 ss1; } s2 = {“ghi”, { “jkl”, “mno” }}; printf(“s1.c[0]=%c\t”, s1.c[0]); printf(“*s1.s=%c\n”, *s1.s); printf(“s1.c=%s\t”, s1.c); printf(“s1.s=%s\n”, s1.s); printf(“s2.cp=%s\t”, s2.cp); printf(“s2.ss1.s=%s\n”, s2.ss1.s); printf(“++s2.cp=%s\t”, ++s2.cp); printf(“++s2.ss1.s=%s\n”, ++s2.ss1.s); 21 } 예제 [해 설] output struct의 멤버로 struct를 사용할 수 있다. s1.c[0]=a *s1.s=d s1.c=abc s1.s=def s2.cp=ghi s2.ss1.s=mno ++s2.cp=hi s2.ss1.s=no
40
예제 8.6 struct의 포인터를 인수로 사용 1 /* File : ex8-6.c
struct의 포인터를 인수로 사용하는 함수 match */ #include <stdio.h> struct student { char name[20]; int id; } student = { “Kim”, 73 }; int main(void) { int id, match(); char *name1 = “Lee”, *name2 = “Kim”; 12 if (id = match(&student, name1)) printf(“%s’s ID is %d.\n”, name1, id); else printf(“He is not %s.\n”, name1); 17 if (id = match(&student, name2)) printf(“%s’s ID is %d.\n”, name2, id); else printf(“He is not %s.\n”, name2); 22 } 23 int match(struct student *r, char *n) 24 { if (strcmp(r->name, n) == 0) return r->id; return 0; /* 실패 */ 28 } 예제 8.6 struct의 포인터를 인수로 사용
41
줄4-7은 name과 id란 멤버를 갖는 struct student를 정의하고
그 멤버값을 “Kim”과 73으로 초기화 한다. 줄 13과 줄 18에서는 각각 변수 student에 저장된 name이 “Lee”인지 또는 “Kim”인지 확인하고 있다. 확인이되면 해당 학생의 id가 반환된다. 함수 match는 첫 인수가 가리키는 구조체의 멤버 name이 가리키는 이름이 둘째 인수와 같은지 strcmp함수를 호출하여 알아보고, 맞으면 해당 학생의 id를 반환한다. 아니면 0을 반환한다. strcmp함수는 비교하는 두 문자열이 같으면 0을 반환함에 주의. 줄26의 r->id는 포인터 r이 가리키는 구조체의 멤버 id를 의미함. 예제 8.6(계속) [해 설] output He is not Lee. Kim’s ID is 73.
42
(1) 함수 add()는 int형 자료를 반환하는 함수이다.
/* 예제 8.7 다음 문장들의 의미는? */ /* (1) */ static int add(int x, int y) { return (x+y); } /* (2) */ typedef struct { char name[20]; int id; } STUDENT; /* */ STUDENT frontstu (STUDENT a, STUDENT b) return ((a.id < b.id) ? a : b); 예제 [해 설] (1) 함수 add()는 int형 자료를 반환하는 함수이다. static지정으로 이 함수는 같은 원시 file내에서만 호출할 수 있다. static을 생략한 일반함수는 외부함수로 다른 file에서도 호출 가능. (2) id 등의 멤버를 갖는 구조체를 STUDENT라고 정의함. 함수 frontstu는 인수로 넘어온 STUDENT형 두 인수의 id를 비교하여 그 값이 작은 인수를 반환한다.
43
두 인수가 가리키는 문자열 중 길이가 짧은 문자열의 포인터를 반환.
/* 예제 8.7(계속) */ /* (3) */ char *shortername_stu(s1, s2) char s1[], s2[]; { int i; i = 0; while (s1[i] != ‘\0’ && s2[i] != ‘\0’) i++; if (s1[i] == ‘\0’) return s1; return s2; } 예제 8.7(계속) [해 설] (3) 문자배열에 대한 포인터를 반환하는 함수. 두 인수가 가리키는 문자열 중 길이가 짧은 문자열의 포인터를 반환.
44
예제 8-8 1 /* File : ex8-8.c 2 struct의 복사 함수 */
#include <stdio.h> struct st { int id; char name[10]; }; 8 void st_copy(struct st *s1, struct st *s2) 10 { int j; s1 -> id = s2 -> id; for (j = 0; j < 10; j++) s1 -> name[j] = s2 -> name[j]; 15 } 16 void st_print(struct st *s) 17 { printf(“번호 = %d, 이름 = %s\n”, s -> id, s -> name); 19 } 20 예제 8-8
45
st_copy(&std1, &std2);는 std2가 가리키는 구조체를 std1이 가리키는 구조체에 복사한다.
21 int main(void) 22 { struct st std1 = {30, “Kim”), std2 = {70, “Lee”); 24 printf(“학생 1 : ”); st_print(&std1); printf(“학생 2 : ”); st_print(&std2); st_copy(&std1, &std2); printf(“\n학생2의 정보를 학생1로 복사한다.\n\n”); printf(“학생 1 : ”); st_print(&std1); printf(“학생 2 : ”); st_print(&std2); 31 } 예제 8-8(계속) output st_copy(&std1, &std2);는 std2가 가리키는 구조체를 std1이 가리키는 구조체에 복사한다. main에서는 구조체 복사(copy) 전과 후의 모습을 확인한다. 학생 1 : 번호 = 30, 이름 = Kim 학생 2 : 번호 = 70, 이름 = Lee 학생2의 정보를 학생1로 복사한다. 학생 1 : 번호 = 70, 이름 = Lee
46
값이 제공되지 않은 2째 행의 3 원소들 m[1][0], m[1][1], m[1][2]는 0으로 초기화 된다.
/* File : ex8-9a.c 다음 코딩의 출력은? */ #include <stdio.h> struct list { int i, j, k; float m[2][3]; } x = { 1, 2, 3, {4.0, 5.0, 6.0} }; 8 int main(void) 10 { printf(“%d\t%.3f\t%.3f\n”, x.j, x.m[0][1], x.m[1][1]); 12 } 예제 8-9(1) [해 설] output x의 int형 멤버 x, y, z는 1, 2, 3으로 초기화된다. x의 float 형 배열 m의 첫 행의 3 원소들 m[0][0], m[0][1], m[0][2]는 4.0, 5.0, 6.0으로 초기화된다. 값이 제공되지 않은 2째 행의 3 원소들 m[1][0], m[1][1], m[1][2]는 0으로 초기화 된다.
47
공용형의 4 멤버 중 x는 6바이트, 나머지 i, j, k는 4바이트 필요하므로 이 공용형은 총 6바이트 차지함
/* File : ex8-9b.c 다음 코딩의 출력은? */ #include <stdio.h> union { char x[2][3]; int i, j, k; } y; 8 int main(void) 10 { y.i = 0; y.x[1][0] = ‘4’; printf(“%d\t%d\t%d\n”, y.I, y.j, y.k); 14 } 예제 8-9(2) [해 설] output 공용형의 4 멤버 중 x는 6바이트, 나머지 i, j, k는 4바이트 필요하므로 이 공용형은 총 6바이트 차지함 문자 ‘4’는 코드값이 52 이다. 정수는 x[0][0], x[0][1], x[0][2],x[1][0]과 겹친다. 정수 4바이트 중 가장 작은 수를 저장하는 바이트가 x[1][0]인 기계의 경우는 아래와 같이 i값, j값, k값이 52이다. 정수 4바이트 중 가장 작은 수를 저장하는 바이트가 x[0][0]인 기계의 경우는 매우 큰 값(52 * 224 = )이 출력된다.
48
/* 예제 8.10 다음 선언들의 의미는? */ /* (1) */ union sign { int svar; unsigned uvar; double dvar; } number; /* (2) */ union { struct { char icon; unsigned color:4; } window1, window2, window3, window4; } screen[25][80]; 예제 [해 설] (1) int 형, unsigned 형 및 double 형 멤버 3 개 중 가장 큰 메모리를 필요로 하는 double형(통상 8바이트) 크기를 갖는 공용형 sign을 선언하고 그 변수 number를 정의함 (2) 공용형 원소 2000개를 갖는 2차원 배열 screen의 선언이다. 각 원소는 4개의 멤버 window1, … window4중 한 개를 가진다.
49
공용형의 두 멤버가 동일한 주소를 갖는다는데 주의하라. 값을 배정한 멤버와 접근하는 멤버가 달라도 에러로 처리되지않음.
1 /* File : ex8-11.c 다음 union형에서 n변경시 x값은 변하는가? */ #include <stdio.h> typedef union int_or_float { int n; float x; } number; 8 int main(void) 10 { number temp; temp.n = 3; printf(“%d %f\n”, temp.n, temp.x); temp.x = 3.0; printf(“%d %f\n”, temp.n, temp.x); 16 } 예제 8-11 공용형의 두 멤버가 동일한 주소를 갖는다는데 주의하라. 값을 배정한 멤버와 접근하는 멤버가 달라도 에러로 처리되지않음. 올바른 사용은 전적으로 프로그래머의 책임이다.
50
(1) struct both형의 2 인수를 받아 struct both형을 반환하는 함수의 포인터들의 배열
/* 예제 8.12 다음 선언들의 의미는? */ /* (1) */ struct both { int a; char b; } (*var[ ]) (struct both, struct both); /* (2) */ union sign { int x; unsigned y; } **var[5][5]; /* (3) */ union sign *(*var[5])[5]; 예제 [해 설] (1) struct both형의 2 인수를 받아 struct both형을 반환하는 함수의 포인터들의 배열 (2) union sign 포인터에 대한 포인터들의 배열의 배열 (3) union sign 포인터들의 배열에 대한 포인터들의 배열
51
screen 의 2000개 원소 중 첫 번째 원소의 저장 모습이다. 14비트 크기임.
/* 예제 8.13 다음 구조형 선언의 기억 형태는? */ struct { unsigned icon:8; unsigned color:4; unsigned underline:1; unsigned blink:1; } screen[25][80]; 예제 [해 설] screen 의 2000개 원소 중 첫 번째 원소의 저장 모습이다. 14비트 크기임.
52
예제 8-14 output 1 /* File : ex8-14.c 2 비트 필드 조작 프로그램 */
비트 필드 조작 프로그램 */ #include <stdio.h> int main(void) { struct { unsigned carry: 2; /* overflow */ unsigned parity: 2; /* 1 = 짝수; 0 = 홀수 */ unsigned acarry: 2; /* 보조 carry */ unsigned zero: 1; /* 결과가 0 */ unsigned sign: 1; /* 결과가 음수 */ } f8080; f8080.carry = f8080.acarry = f8080.sign = 0; f8080.parity = f8080.zero = 1; if (f8080.carry == 0) printf(“carry 없음\n”); if (f8080.parity == 0) printf(“짝수 parity\n”); if (f8080.acarry == 0) printf(“보조 carry 없음\n”); if (f8080.zero == 0) printf(“결과가 0이 아님\n”); if (f8080.sign == 0) printf(“결과가 양수임\n”); 20 } 예제 output carry 없음 보조 carry 없음 결과가 양수임
Similar presentations