Presentation is loading. Please wait.

Presentation is loading. Please wait.

처음으로 배우는 C 프로그래밍 제4부 복합 데이터 형 제 10 장 구조체.

Similar presentations


Presentation on theme: "처음으로 배우는 C 프로그래밍 제4부 복합 데이터 형 제 10 장 구조체."— Presentation transcript:

1 처음으로 배우는 C 프로그래밍 제4부 복합 데이터 형 제 10 장 구조체

2 구조체 집단을 구성하는 개개 원소들이 어떻게 배치되어 있는지 혹은 어떻게 조직화되어 있는지를 나타냄 예:
회사 정보: 회사원 정보와 부서 정보 정부의 조직: 조직원, 조직의 형태, 조직의 배치 정보 개 개의 자료 항목이 어떻게 배치되어 있는지를 잘 설명하고 있는 단위(unit) 예 (우편물 주소) Name: (자료 항목) - 개체(entity) Street Address: (자료 항목) - 개체(entity) City: (자료 항목) - 개체(entity) State: (자료 항목) - 개체(entity) Zip Code: (자료 항목) - 개체(entity) 레코드(record): 개개의 자료 항목을 모아 형성한 더 큰 집단 => 구조체 구조체 형태: 개개의 자료 항목의 기호명, 자료형과 배치로 구성 구조체 내용: 기호명에 저장된 실 자료를 의미

3 구조체(계속) 구조체 형태: 개개의 자료 항목의 기호명, 자료형과 배치로 구성 Name Street Address City
State Zip Code 구조체 내용: 기호명에 저장된 실 자료를 의미 Rhona Bronson-Karp 614 Freeman Street Orange NJ 07052

4 단일 구조체 자료 항목, 구조체 멤버 구조체 변수 구조체의 선언 자료형, 자료 명, 자료 항목 배치 작성
구조체 정의 예 (년월일을 저장하는 구조체) struct { int month; /* 월 */ int day; /* 일*/ int year; /* 년*/ } birth; 구조체 멤버 접근 방법(연산자 .) birth.month (birth 구조체 멤버 month 접근) birth.year (birth 구조체 멤버 year 접근) 자료 항목, 구조체 멤버 구조체 변수

5 #include <stdio.h>
void main(void) { struct { int month; int day; int year; } birth; birth.month = 10; birth.day = 12; birth.year = 63; printf("My birth date is %d/%d/%d.", birth.month, birth.day, birth.year); } 출력 결과 My birth date is 10/12/63.

6 구조체 정의 변수 명을 갖는 구조체 정의 단일 변수 여러 변수
struct {int month; int day; int year;} birth; 여러 변수 struct {int month; int day; int year;} birth, current; birth.month, birth.day, birth.year current.month, current.day, current.year

7 구조체 정의 (계속) 구조체 템플리트(template) 구조체 템플리트를 이용한 변수 선언
변수명이 없는 정의 struct Date { /* Date <- 구조체 태그(tag) 명, 구조체 이름 */ int month; int day; int year; }; 구조체 템플리트(template) 구조체 템플리트를 이용한 변수 선언 struct Date birth, current; 멤버 접근 birth.month, birth.day, birth.year current.month, current.day, current.year

8 구조체 템플리트 선언 구조체 멤버의 초기화 struct Date birth = {10, 12, 63};
#include <stdio.h> struct Date { int month; int day; int year; }; void main(void) { (1) struct Date birth; (2) birth.month = 10; (3) birth.day = 12; (4) birth.year = 63; printf("My birth date is %d/%d/%d", birth.month, birth.day, birth.year); } 구조체 템플리트 선언 구조체 멤버의 초기화 struct Date birth = {10, 12, 63};

9 구조체 선언 예 회사원 정보 회사원 정보를 위한 구조체 템플리트선언 구조체 정의와 초기화
Name Identification Number Regular Pay Rate Overtime Pay Rate 회사원 정보를 위한 구조체 템플리트선언 struct Pay_rec { char name[20]; int id_num; float reg_rate; float ot_rate; } ; 구조체 정의와 초기화 struct Pay_rec employee = {"H. Price", 12387, 15.89, 25.50};

10 사람의 생년월일을 위한 구조체 Date 구조체 사용 멤버 접근 방법 struct {
char name[20]; /* 이름을 저장하는 변수 */ struct Date birth; /* 생년월일을 저장하는 변수 */ } person; 멤버 접근 방법 person.name person.birth.month person.birth.day person.birth.year

11 구조체 메모리 할당 aPoint x y 구조체에 대한 메모리 할당 tag_name : 구조체의 이름
구조체 템플리트(틀) 정의는 구조체의 모양을 정의하며 그 형식은 다음과 같음 struct tag_name{ type1 member1; type2 member2; : typen membern; }; x-y 좌표 상에서 “하나의 점과 그 이름을 표시하는 구조체”의 예는 다음과 같음 예) struct aPoint { int x; int y; char name[10]; tag_name : 구조체의 이름 type1, … typen : 각 멤버의 자료형 member1, … membern : 각 멤버의 이름 Name[1] aPoint Name[9] Name[0] x y 구조체에 대한 메모리 할당

12 구조체 템플리트 정의와 변수선언 struct tag_name { type1 member1; type2 member2; :
구조체 템플리트 정의와 구조체 변수 선언을 한 번에 할 수 있음 struct tag_name { type1 member1; type2 member2; : typen membern; } struct_variables, ... ; 예) struct aPoint { int x; int y; char name[5]; } pt1, pt2, pt3; 청주 (10, 20, 청주) (10, 15, 대전) pt1

13 구조체 배열 사원에 대한 자료 사원번호 사원이름 사원급여지급비율
사원번호 사원이름 사원급여지급비율 ========================================== Abrams, B <= 첫 번째 레코드 Bohm, P <= 두 번째 레코드 Donaldson, S <= 세 번째 레코드 Ernst, T <= 네 번째 레코드 Gwodz, K <= 다섯 번째 레코드 Hanson, H <= 여섯 번째 레코드 Monroe, G <= 일곱 번째 레코드 Price, S <= 여덟 번째 레코드 Robbins, L <= 아홉 번째 레코드 Willians, B <= 열 번째 레코드 정수형 배열 문자형 배열 실수형

14 구조체 배열(계속) 사원을 위한 구조체 사원들의 정보를 저장하기 위한 구조체 배열
struct Pay_rec { long idnum; char name[20]; float rate;}; 사원들의 정보를 저장하기 위한 구조체 배열 struct Pay_rec empolyee[10]; employee[0].rate : 첫번째 사원의 급여 지급 비율 employee[4].idnum : 다섯번째 사원의 사원 번호

15 #include <stdio.h>
struct Pay_rec { long id; char name[20]; float rate; }; /* 전역 템플리트 구성 */ void main(void) { int i; struct Pay_rec employee[10] = { 32479, "Abrams, B.", 6.72, 33623, "Bohm, P.", , 34145, "Donaldson, S.", 5.56, 35987, "Ernst, T.", 5.43, 36203, "Gwodz, K.", 8.72, 36417, "Hanson, H.", 7.64, 37634, "Monroe, G.", 5.29, 38321, "Price, S.", 9.67, 39435, "Robbins, L.", 8.50, 39567, "Willians, B.", 7.20 }; for (i=0; i<5; i++) printf("\f2 nld %-20s %4.2f", employee[i].id, employee[i].name, employee[i].rate); } /* end of main */ 출력결과 32479 Abrams, B 33623 Bohm, P 34145 Donaldson, S 35987 Ernst, T 36203 Gwodz, K

16 구조체 전달 struct { int id_num; double pay_rate; double hours;
구조체 멤버의 전달 스칼라(scalar) 변수와 같은 방법으로 전달 구조체 전달(값에 의해) struct { int id_num; double pay_rate; double hours; } emp; display(emp.id_num); calc_pay(emp.pay_rate, emp.hours); calc_net(emp);

17 The net pay for employee 6782 is $361.66
#include <stdio.h> struct Employee { int id_num; double pay_rate; double hours; }; void main(void) { struct Employee emp = 6782, 8.93, 40.5; double net_pay; double c_net(struct Employee); net_pay = calc_net(emp); /* emp로 값의 복사본 전달 */ printf("The net pay for employee %d is $%6.2f", emp.id_num, net_pay); } double calc_net(struct Employee temp) return (temp.pay_rate * temp.hours); 출력결과 The net pay for employee 6782 is $361.66

18 구조체 전달(계속) 구조체 전달(주소에 의한) 피호출문 호출문 void calc_net(struct Employee *pt)
} 호출문 calc_net(&emp);

19 예) struct Employee *pt1, *pt2, *pt3; 포인터 변수로부터 구조체의 멤버를 참조하는 방법
구조체 타입의 포인터 변수 예) struct Employee *pt1, *pt2, *pt3; 포인터 변수로부터 구조체의 멤버를 참조하는 방법 포인터의 성질을 이용한 방법 (*pt1).hours ‘->’연산자를 이용한 방식 pt1 -> hours ‘->’연산 ‘->’연산자의 왼쪽은 구조체의 주소, 오른쪽은 그의 멤버이름을 넣어야 함 구조체 연산자 . 와 -> 는 함수의 ( )와 배열 첨자의 [ ]와 함께 연산 순위가 가장 높음 그러므로 *point.hours는 *(point.hours)와 같은 효과를 지니고, ++pt->hours는 ++(pt-> hours)와 같은 효과를 지닌다.

20 *pt.hours = *(pt.hours) <= 프로그램 오류
*pt == (*pt).id_num (*pt).id_num == pt->id_num (*pt).pay_rate == pt->pay_rate (*pt).hours == pt->hours (*pointer).member => pointer->member

21 주소에 의해 구조체 전달 예 #include <stdio.h> struct Employee { int id_num;
double pay_rate; double hours; }; void main(void) { struct Employee emp = 6782, 8.93, 40.5; double net_pay, double c_net(struct Employee *); net_pay = calc_net(&emp); /* emp로 값의 복사본 전달 */ printf("The net pay for employee %d is $%6.2f", emp.id_num, net_pay); } double calc_net(struct Employee *temp) return (temp->pay_rate * temp->hours);

22 구조체 포인터 연산 pt++; ++pt; pt--; --pt; ++pt->hours;

23 구조체 반환 함수의 반환 값으로 구조체를 받기를 원하는 경우 스칼라(scalar) 값을 반환할 때와 같은 방법으로 구조체를 반환 #include <stdio.h> struct Employee { int id_num; double pay_rate; double hours; }; struct Employee get_vals(void) { struct Employee em; …. return em; } 구조체반환 void main() { struct Employee emp; ... emp = get_vals(); /*함수 호출*/ } emp.id_num = em.id_num; emp.pay_rate = em.pay_rate; emp.hours = em.hours

24 #include <stdio.h>
struct Employee { int id_num; double pay_rate; double hours; }; void main(void) { struct Employee emp; struct Employee get_vals(void); emp = get_vals(); printf("\f2 nThe employee id number is %d", emp.id_num); printf("The employee pay rate is $%5.2f", emp.pay_rate); printf("The employee hours are %5.2f", emp.hours); } struct Employee get_vals(void) struct Employee new_emp; new_emp.id_num = 6789; new_emp.pay_rate = 16.25; new_emp.hours = 38.0; return (new_emp); 출력결과 The employee id number is 6789 The employee pay rate is $16.25 The employee hours are 38.00

25 연결 리스트(Linked List) 자료 처리 방법
특정 순서로 존재하는 레코드(record)에 새로운 레코드를 삽입하거나 기존의 레코드를 삭제할 때 존재하는 레코드가 계속적으로 그 순서를 유지하도록 함 예 (알파벳순서로 정렬된 전화번호 목록) Acme, Sam (201) Dolan, Edith (213) Lanfrank, John (415) Mening, Stephanie (914) Zemann, Harold (718)

26 연결리스트(계속) struct person { char name[20]; char telnum[20]; };
배열 구조를 사용하는 경우 struct person { char name[20]; char telnum[20]; }; 삽입과 삭제의 문제점 발생 struct person hb[10]; Zemann, Harold (718) Acme, Sam (201) Dolan, Edith (213) Lanfrank, John (415) Mening, Stephanie (914) hb[0] hb[1] hb[2] hb[3] hb[4]

27 연결 리스트(계속) 연결 리스트는 간단한 구조체 집합으로 각 구조체는 리스트 내에서 논리적으로 순서화된 구조체 주소를 갖는 적어도 하나의 멤버를 포함 물리적 측면:물리적으로 적절한 순서로 저장되기보다는 오히려 새로운 레코드가 리스트에 추가될 때 물리적으로 컴퓨터의 저장장소내 사용 가능한 임의의 공간에 추가됨 논리적 측면:레코드들은 자기 앞의 레코드가 자신의 주소를 가리키게 함으로써 서로 연결됨 프로그래밍 관점: 처리될 현재의 레코드는 다음 레코드가 물리적으로 어디에 저장되어 있든지 무관하게 다음 레코드의 주소를 포함함 구조체 포인터

28 연결 리스트(계속) 연결 리스트 삽입 (June Hagar 자료 삽입)

29 연결 리스트(계속) 연결리스트(삭제)

30 연결 리스트(계속) Employee number 12345 was paid $456.20 구조체에 구조체 포인터 추가
#include <stdio.h> struct Test { int id_num; double *pt_pay; }; void main(void) { struct Test emp; double pay = ; emp.id_num = 12345; emp.pt_pay = &pay; printf("Employee number %d was paid $%6.2f'', emp.id_num, *emp.pt_pay); } 출력결과 Employee number was paid $456.20

31 연결 리스트(계속) 구조체 포인터 전화번호 저장을 위한 연결 리스트 구조체 #include <stdio.h>
struct Tele_typ { char name[30]; char phone_no[15]; struct Tele_typ *nextaddr; }; 구조체 포인터

32 void main(void) { struct Tele_typ t1 = ''Acme, Sam'', ''(201) ''; struct Tele_typ t2 = ''Dolan, Edith'', ''(213) ''; struct Tele_typ t3 = ''Lanfrank, John'', ''(415) ''; Tele_typ *first; /* 구조체 포인터 생성 */ first = &t1; /* t1 주소를 first 에 저장 */ t1.nextaddr = &t2; /* t2 주소를 t1.nextaddr에 저장 */ t2.nextaddr = &t3; /* t3 주소를 t2.nextaddr에 저장 */ t3.nextaddr = NULL; /* NULL 를 t3.nextaddr에 저장 */ printf(''%s %s %s'', first->name, t1.nextaddr->name, t2.nextaddr->name); } 출력결과 Acme, Sam Dolan, Edith Lanfrank, John

33

34 구조체를 포인터로 전달 void main(void) #include <stdio.h> {
struct Tele_typ t1 = "Acme, Sam", "(201) "; struct Tele_typ t2 = "Dolan, Edith", "(213) "; struct Tele_typ t3 = "Lanfrank, John", "(415) "; Tele_typ *first; /* 구조체 포인터 생성 */ first = &t1; /* t1 주소를 first 에 저장 */ t1.nextaddr = &t2; /* t2 주소를 t1.nextaddr에 저장 */ t2.nextaddr = &t3; /* t3 주소를 t2.nextaddr에 저장 */ t3.nextaddr = NULL; /* NULL 를 t3.nextaddr에 저장 */ display(first); /* 구조체 first의 주소를 전달 */ } #include <stdio.h> struct Tele_typ { char name[30]; char phone_no[15]; struct Tele_typ *nextaddr; };

35 void display(struct Tele_typ *contents)
/*contents는 Tele_typ 형 구조체의 포인터 변수임 */ { while (contents != NULL) /* 연결 리스트에 저장된 모든 구조체 정보를 출력 */ printf("%30s %-20s %s", contents->name, contents->phone_no); contents = contents->nextaddr; } return; 출력결과 Acme, Sam (201) Dolan, Edith (213) Lanfrank, John (415)

36 동적 메모리 할당 프로그램에서 정의된 모든 변수는 그 변수의 값을 저장하기에 충분한 기억장소를 컴퓨터 메모리로부터 할당 받음
특정 메모리 위치가 변수를 위해 확보되면, 변수의 유효 범위(life time)내에서는 그 위치가 사용되든 그렇지 않든 그 위치는 변하지 않는다 예:500 개의 정수를 저장하는 배열 사용하는 정수: 10개, 490개의 기억 공간 낭비 => 효율적인 기억 장소 필요성 필요할 때 필요한 만큼 기억장소를 확보 불필요한 기억장소는 해제 예: 연결 리스트(삽입 정보, 정보 삭제)

37 동적 메모리 할당 함수 동적 메모리 할당을 위한 include 함수명: stdlib.h 메모리 할당 함수 - 함수명: malloc(int ) - 기능: 요구된 바이트 수() 만큼 기억장소를 확보한다. 성공적으로 기억장소를 확보하면 기억장소의 시작 주소를 반환하고 충분한 메모리가 없는 경우 NULL를 반환한다. -예: int *pt; pt = malloc(200 * sizeof(int)); 메모리 해제 함수 -함수명: free() -기능:미리 확보된 바이트의 블록을 해제한다. 해제될 기억장소의 시작 주소가 이 함수의 인자로 사용된다. -예: free(pt);

38 배열의 크기를 입력 받아 그 만큼의 배열을 위한 기억 장소 할당 int numgrades;
int *grades; /* 정수형 포인터 변수 정의 */ printf("Enter the number of grades to be processed: "); scanf("%d", &numgrades); /* 요구된 만큼의 정수형 배열을 위한 기억장소 할당 */ grades = (int *) malloc(numgrades * sizeof(int));

39 #include <stdio.h>
#include <stdlib.h> void main(void) { int numgrades; int *grades; /* 정수형 포인터 변수 정의 */ printf("Enter the number of grades to be processed: "); scanf("%d", &numgrades); /* 요구된 만큼의 정수형 배열을 위한 기억장소 할당 */ grades = (int *) malloc(numgrades * sizeof(int)); if (grades == (int *) NULL) {/* 동적기억장소할당이 정상적으로 이루어졌는지를 검사 */ printf("Failed to allocate grades array "); exit(1); }

40 An array was created for 4 integers
for (i=0; i < numgrades; i++) { printf(" Enter a grade: "); scanf("%d", &grades[i]); } printf("\f2 nAn array was created for %d integers", numgrades); printf("\f2 nThe vales stored in the array are:"); for (i=0; i < numgrades; i++) printf(" %d", grades[i]); free(grades); 실행결과 Enter the number of grades to be processed: 4 Enter a grade: 85 Enter a grade: 96 Enter a grade: 77 Enter a grade: 92 An array was created for 4 integers The value stored in the array are: 85 96 77 92

41 구조체 동적 기억장소 할당 struct Office_info { 자료 멤버들; };
struct Office_info *off; /*할당된 주소를 저장하기 위한 포인터 변수 */ /* 구조체를 저장하기 위한 공간 확보 */ off = (struct Office_info *) malloc(sizeof(struct Office_info)); /* 공간이 할당되었는지를 점검 */ if (off == (struct Office_info *) NULL) { printf("\f2 nAllocation of Office info record failed"); exit(1) }

42 동적 연결 리스트 초기 리스트

43 동적 연결 리스트 삽입 예 Carter 삽입

44 동적 연결 리스트 삽입 방법 INSERT (새로운 레코드를 연결 리스트에 추가) {
-새로운 레코드를 위한 공간을 동적으로 할당 if 리스트에 임의의 레코드가 존재하지 않음 -새로운 레코드의 주소 필드를 NULL로 지정 -첫 번째 레코드 포인터를 새롭게 생성된 레코드의 주소로 지정 else -새로운 레코드가 리스트의 어느 위치에 놓여져야 할 것인지를 결정 if 레코드가 리스트의 첫 번째 레코드로 존재해야 함 -첫 번째 레코드 포인터의 값을 새롭게 추가된 레코드의 주소 필드에 복사 -첫 번째 레코드 포인터의 주소를 새롭게 추가된 레코드의 주소로 지정 -추가된 레코드의 바로 앞에 놓일 레코드의 포인터 멤버의 값을 새롭게 추가된 레코드의 주소 필드에 복사 새롭게 추가된 레코드의 주소로 지정 /* endif */ /* endif } /* end of INSERT

45 동적 연결 리스트 삽입 새로운 레코드의 선형 탐색(LINEAR LOCATION of a NEW RECORD)
if 새로운 레코드의 키이 필드가 첫 번째 레코드 키이 필드보다 작으면 - 새로운 레코드가 첫 번째 레코드임 else while (리스트에 레코드가 있음) { - 새로운 레코드의 키이 값과 각 레코드의 키이 값과 비교 - 새로운 레코드 키가 두 개의 레코드사이에 존재하거나 혹은 리스트의 끝에 속하는 경우 비교를 멈춤 } endwhile endif

46 레코드 삽입 예 #include <stdio.h> #include <stdlib.h>
#define MAXCHARS 30 /* 연결 리스트 레코드의 선언 */ struct Name_rec { char name[MAXCHARS]; struct Name_rec *next_addr; }; /* 첫 번째 레코드 포인터의 정의 */ struct Name_rec *first_rec; void main(void) { void read_insert(void); /* 함수 프로토타입 */ void display(void); first_rec = NULL; /* 리스트 포인터 초기화 */ read_insert(); display(); }

47 /* 이름을 입력받아 이를 연결 리스트에 삽입 */
void read_insert(void) { char name[MAXCHARS]; void insert(char []); printf("\f2 nEnter as many names as you wish, one per line"); printf("\f2 nTo stop entering names, enter a single x "); while(1) printf("Enter a name: "); gets(name); if (strcmp(name, "x") == 0) break; insert(name); }

48 void insert(char *name)
{ struct Name_rec *locate(char *); /* 함수 프로토타입 */ struct Name_rec *newaddr, *here; /* Name_rec 형 구조체 포인터 */ newaddr = (struct Name_rec *) malloc(sizeof(struct Name_rec)); if (newaddr == (struct Name_rec *) NULL) { /* 주소를 점검 */ printf("\f2 nCould not allocate the requested space"); exit(1); } /* 새로운 레코드가 어디에 놓여져야 할지를 결정, 모든 포인터 멤버를 갱신 */ if (first_rec == NULL) {/* 현재 리스트에 존재하는 레코드가 없는 경우 */ newaddr->next_addr = NULL; first_rec = newaddr; else if (strcmp(name, first_rec->name) < 0) { /* 리스트에 첫 번째 레코드로 추가되는경우 */ newaddr->next_addr = first_rec; } else {/* 레코드가 리스트의 첫 번째 레코드가 아닌 경우 */ here = locate(name); newaddr->next_addr = here->next_addr; here->next_addr = newaddr; strcpy(newaddr->name, name);

49 /* 존재하는 연결 리스트에 새로 추가될 레코드의 삽입될 위치를 결정 */
struct Name_rec *locate(char *name) { struct Name_rec *one, *two; one = first_rec; two = one->next_addr; if (two == NULL) return (one); /* 새로운 레코드는 존재하는 단일 레코드 다음에 삽입될 것임 */ while(1) { if (strcmp(name, two->name) <0) /* 리스트내의 이 위치에 레코드를 삽입한다 */ break; else if (two->next_addr == NULL) { /* 마지막 레코드 다음에 위치 */ one = two; } else { /* 계속적으로 삽입될 위치를 찾음 */ two = one->next_addr; return (one);

50 /* 연결 리스트로부터 name을 출력 */ void display(void) { struct Name_rec *contents; contents = first_rec; printf("\f2 nThe names currently on the list are:"); while (contents != NULL) { printf("%s", contents->name); contents = contents->next_addr; } return; 출력결과 Enter as many names as you wish, one per line To stop entering names, enter a single x Enter a name: Binstock Enter a name: Arnold Enter a name: Duberry Enter a name: Carter Enter a name: x The names currently on the list are: Arnold Binstock Carter Duberry

51 공용체(Union) 공용체는 사용할 때마다 이질적인 멤버의 자료형과 다른 크기를 가질 수 있도록 하는 구조체임
비교) 파스칼의 가변 레코드와 동일함 하나의 메모리 장소에 여러 데이터 형의 자료를 저장 가능하도록 지원함; 즉, 여러 자료형의 변수가 하나의 주소를 공유하게 함 그러나, 여러 값이 동시에 저장될 수는 없음; 즉, 한 시점에는 하나의 자료만 저장됨 공용체의 선언은 구조체와 동일함 union u_tag { int ival; float fval; char *sval; } u, *uptr, uarray[10]; 공용체 u_tag의 크기는 int, float, char 중에서 가장 큰 것으로 할당됨 비교) 구조체의 크기는 모든 멤버들의 크기의 합과 같음

52 공용체(계속) 구조체에서 정의된 . 과 -> 연산자도 공용체에서 동일한 의미로 사용
u.fval uptr->ival 공용체 u에는 세 가지 자료형 (int, float, char) 중 어느 것으로도 할당 가능 그러나, 할당된 값의 참조는 가장 최근에 할당한 자료형으로만 가능함 (이는 전적으로 프로그래머 책임임 ) ufval = 2.0; /* 10이 지워지고 2.0이 저장; 4byte사용 */ u.sval = “I am a boy,”; /*2.0이 지워지고 주소가 저장; 4byte사용 */ uptr = &u; x = uptr -> fval; /* Error!! 가장 최근에 문자 포인터로 사용했기 때문에 */ u.ival = 10; /* 10이 저장; 2byte사용 */ union u_tag { int ival; float fval; char *sval; } u, *uptr, uarray[10];

53 공용체(계속) 구조체 안에 공용체을, 반대로 공용체 안에 구조체를 선언할 수도 있음 char *name; int flags;
struct { /*구조체 이름 생략 가능!!*/ char *name; int flags; int utype; union { int ival; float fval; char *sval; } u; } symtab[NSYM]; if ( symtab[n].utype == INT) printf(“%d\n”, symtab[n].u.ival); else if (symtab[n].utype == FLOAT) printf(“%f\n”, symtab[n].u.fval); else if (symtab[n].utype == STRING) printf(“%s\n”, symtab[n].u.sval);

54 범하기 쉬운 오류 구조체와 공용체가 관계 수식으로 사용될 수 없기 때문에 발생한다. 예를 들어, Tel_type과 Phon_type이 같은 형의 구조체일 지라도 수식 Tel_typ == Phon_type은 프로그래밍 오류이다 포인터가 구조체와 공용체와 관계할 때 발생하는 포인터 오류이다. 공용체와 관련 된 것으로 공용체가 특정한 시점에 공용체를 구성하는 멤버들 중 하나의 멤버만을 나타내고 있으므로 현재 저장된 변수 값이 무엇인지를 꼭 알고 있어야 한다. 만약 공용체에 저장된 값을 잘못된 변수를 통해 접근하면 원하지 않은 이상한 값을 여러분은 접근할 것이다.


Download ppt "처음으로 배우는 C 프로그래밍 제4부 복합 데이터 형 제 10 장 구조체."

Similar presentations


Ads by Google