자료 구조: Chapter 3 (2)구조체, 포인터 2017. 3. 28 하 상 호
3장 목차 배열 구조체 포인터
구조체 구조체(structure): 타입이 다를 수 있는 데이터를 하나로 묶는 방법 배열(array): 타입이 같은 데이터들을 하나로 묶는 방법 구조체 배열 필드 1 char carray[100]; struct example { char cfield; int ifield; float ffield; double dfield; }; struct example s1;
구조체 선언 구조체의 선언과 구조체 변수의 생성 typedef을 이용하여 구조체에 다른 타입 이름 부여 struct person { char name[10]; // 문자배열로 된 이름 int age; // 나이를 나타내는 정수값 float height; // 키를 나타내는 실수값 }; struct person student; // 구조체 변수 선언 typedef을 이용하여 구조체에 다른 타입 이름 부여 typedef struct person { // typedef는 다른 타입 이름 부여 char name[10]; int age; float height; } person; person student; // 구조체 변수 선언
구조체 연산 구조체 할당은? 구조체 비교는? struct person { char name[10]; // 문자배열로 된 이름 int age; // 나이를 나타내는 정수값 float height; // 키를 나타내는 실수값 }; main() { person a, b; b = a; // ? } 구조체 비교는? main() { if( a > b ) printf("a가 b보다 나이가 많음"); // ? }
자체참조 구조체 자체 참조 구조체(self-referential structure): 필드중에 자기 자신을 가리키는 포인터가 한 개 이상 존재하는 구조체 연결 리스트나 트리에 많이 등장 struct ListNode { char data; struct ListNode *link; };
C의 포인터(pointer) 포인터: 다른 변수의 주소를 가지고 있는 변수 주소 변수 a 포인터 p char a='A'; 26 ‘A’ 변수 a 주소 포인터 p 포인터: 다른 변수의 주소를 가지고 있는 변수 char a='A'; char *p; p = &a;
C의 포인터(pointer) 포인터: 다른 변수의 주소를 가지고 있는 변수 포인터가 가리키는 내용의 변경: * 연산자 사용 26 ‘A’ 변수 a 주소 포인터 p 포인터: 다른 변수의 주소를 가지고 있는 변수 char a='A'; char *p; p = &a; 포인터가 가리키는 내용의 변경: * 연산자 사용 26 ‘B’ 변수 a 주소 포인터 p *p= 'B';
C의 포인터(pointer) 다음 C 코드의 각 문장 의미는 무엇인가? int a = 10, *q, *r; // a) q = &a; // b) *r = *q; // c) printf(“%p\t%d”, r, *r); // d)
포인터 연산자 26 ‘A’ 변수 a 포인터 p &a *p & 연산자: 변수의 주소를 추출 * 연산자: 포인터가 가리키는 곳의 내용을 추출 int a; // 정수 변수 선언 int *p; // 정수 포인터 선언 int **pp; // 정수 포인터의 포인터 선언 p = &a; // 변수 a와 포인터 p를 연결 pp = &p; // 포인터 p와 포인터의 포인터 pp를 연결
배열과 포인터 배열의 이름은 상수 포인터 배열 이름에는 첫번째 요소의 주소가 포함되나 다른 주소를 할당 받을 수 없음 a ≡ &a[0] 10 A[0] A 14 A[1] 18 A[2] 22 A[3] 26 A[4] 30 A[5]
포인터 연산: 증감연산자 배열과 연관되어 사용 연산자 우선순위: () [] -> . // left to right ! ++ -- * & // right to left p // 포인터 *p // p가 가리키는 값 *p++ // ≡ *(p++): p가 가리키는 위치를 가져오고(다음에 p는 한 칸 증가한다), //그 위치에 포함된 값을 반환. *p-- // ≡ *(p--): p가 가리키는 위치를 가져오고(다음에 p는 한 칸 감소한다), //그 위치에 포함된 값을 반환. (*p)++ // p가 가리키는 값을 가져오고, 다음에 그 값을 증가시킨다. *++p // ≡ *(++p): p를 한 칸 증가하고, 증가된 p가 가리키는 값을 가져온다 *--p // ? ++*p // ≡ ++(*p): p가 가리키는 값을 가져오고, 그 값을 증가하고, // 그 증가된 값을 가져온다. --*p // ?
포인터 연산: 증감연산자 printf(“%The address stored in p is %p\n”, p); printf(“%The address pointed by p+1 is %p\n”, p+1); printf(“%The address pointed by p-3 is %p\n”, p -3); printf(“%d\n”, *p); Printf(“%d\n”, *(p-3)); printf(“%d\n”, *p++); printf(“%d\n”, *p--); printf(“%d\n”, *++p); printf(“%d\n”, *--p);
구조체의 포인터 구조체의 요소에 접근하는 연산자: -> main() { struct { int i; float f; } s, *ps; ps = &s; ps->i = 2; // (*ps).i = 2; ps->f = 3.14; } 3.14 98 2 ps s s.I = ps->i s.f = ps->f
포인터 용도: 참조-호출 표현 함수의 매개변수를 포인터로 전달 void swap(int* px, int* py) { int tmp; tmp = *px; *px = *py; *py = tmp; } main() int a=1,b=2; printf("swap을 호출하기 전: a=%d, b=%d\n", a,b); swap(&a, &b); printf("swap을 호출한 다음: a=%d, b=%d\n", a,b);
포인터 용도: 동적 메모리 할당 전형적인 동적 메모리 할당 코드 동적 메모리 할당 관련 라이브러리 함수 main() { int* pi; pi = (int *)malloc(sizeof(int)); // 동적 메모리 할당 ... … // 동적 메모리 사용 free(pi); // 동적 메모리 반납 } 동적 메모리 할당 관련 라이브러리 함수 void * malloc(size_t size) // 메모리 할당 free(void * ptr) // ptr이 가리키는 메모리 반환 sizeof(var) // 변수나 타입의 크기 반환(바이트 단위) stdlib.h 상에 정의
동적 메모리 할당 예제 struct exRec { int number; char name[10]; }; void main() struct exRec *p; p=(struct exRec *)malloc(2*sizeof(struct exRec)); // ? if(p==NULL){ fprintf(stderr, "can't allocate memory\n") ; exit(1) ; } p->number=1; //? strcpy(p->name,"Park"); (p+1)->number=2; //? strcpy((p+1)->name,"Kim"); //? // 2개의 레코드를 출력하라. // … ?? free(p);
동적 자료구조 동적 메모리 할당을 통해서 동적으로 생성되는 자료구조 다음의 구조체를 3개 생성하여 한 줄로 연결하라. 10 struct linkedNum { int val; struct linkedNum *next; } val next 10 20 30
예제: 동적 자료구조 30 20 10 struct linkedNum{ int val; struct linkedNum *next; }; int main() { struct linkedNum first; // 리스트를 가리키는 포인터 변수 struct linkedNum n1, n2, n3; // 리스트를 구성하라. // 리스트를 출력하라 (while 문을 이용하라) } first n1 n2 n3 30 20 10