260 likes | 333 Views
구조체: Structure 와 포인터2. 집합적 변수 생성 가능. structure_declaration ::= struct_specifier declarator_list ; struct_specifier ::= struct tag_name | struct tag_name opt { { member_declaration } 1+ } tag_name ::= identifier member_declaration ::= type_specifier declaration_list ;
E N D
집합적 변수 생성 가능 structure_declaration ::= struct_specifier declarator_list ; struct_specifier ::= structtag_name | struct tag_nameopt { { member_declaration}1+} tag_name ::= identifier member_declaration ::= type_specifierdeclaration_list ; declaration_list ::= declarator { , declarator }0+ struct card { int pips; char suit; } c1, c2; struct card { int pips; char suit; }; struct card c1, c2; c1.pips = 3; c1.suits = ‘s’; c2 = c1;
typedef 구문 • 별명을 정하여 형정의를 할 수 있음 typedef int INTEGER; INTEGER a; typedef struct card card; typedef struct card { int pips; char suit; } card; card c1, c2;
구조체의 함수에 적용 (1) typedef struct employee_data { char name[25]; int employee_id; struct dept department; struct home_address *a_ptr; double salary; … } employee_data; • 함수 호출 절차 • (call-by-value) • 호출시에, e1 을 e 에 복사 • 리턴시에, e 를 e1으로 복사 • 구조체의 복사시 memberwise copy employee_data update(employee_data e) { … e.department.dept_no = n; … return e; } employee_data e1; e1 = update(e1); 문제점: 구조체의 메모리 요구량이 큰 경우, 복사에 따른 부하가 커진다.
구조체의 함수에 적용 (2) 이 경우, 함수 호출에 따른 오버헤드는 포인터 변수 복사. void update(employee_data *p) { … p->department.dept_no = n; (p->department).dept_no = n; (*p).dept_no = n; … return e; } employee_data e1; update(&e1); 구조체에 대한 포인터 변수 사용시, 구조체의 내용을 접근하는 연산자: ->
동적 메모리 할당 (1) #include<stdlib.h> #include<string.h> … void f() { char *s; s = (char*)malloc(sizeof(char)*8); s[0] = ‘d’; s[1] = ‘y’; s[2] = ‘n’; s[3] =‘a’; s[4] = ‘m’; s[5] = ‘i’; s[6] = ‘c’; s[7] = ‘\0’; strcpy(s, “dynamic”); free(s); }
동적 메모리 할당 (2) • 컴파일시에 메모리의 할당 크기가 정해지는 것이 아니라, 프로그램 실행중에 가변적인 크기의 메모리를 할당/해제 할 수 있게 됨 • 함수내에서 할당된 동적 메모리는 함수 종료후에 자동 해제 되지 않음 • 반드시, malloc/free 을 쌍으로 호출하는 습관을 익힐 것
동적 메모리 할당 (3) • #include <stdlib.h> • void*malloc(size_tsize); • voidfree(void*memblock);
포인터 주소 연산 0x00430180 0x00430150 0x00430151 0x00430184 0x00430188 0x00430152 int *pI; pI = (int*)malloc(sizeof(int)*5); pI[0]=0x10ae; pI[1]=0x10a7; pI[2]=0x10b4; pI[3]=0x30ff; pI[4]=0x7f77; *(pI)=0x10ae; *(pI+1)=0x10a7; *(pI+2)=0x10b4;*(pI+3)=0x30ff; *(pI+4)=0x7f77; char *pC; pC = (char*)malloc(sizeof(char)*5); pC[0]=‘A’; pC[1]=‘B’; pC[2]=‘C’; pC[3]=‘D’; pC[4]=‘\0’; *(pI)=‘A’; *(pI+1)=‘B’; *(pI+2)=‘C’; *(pI+3)=‘D’; *(pI+4)=‘\0’;
포인터 이해 (1) • int p; /* p is integer */ • int p[7]; /* p is array[7] of integer */ • int *p; /* p is pointer to integer */ • int *p[7]; /* p is array[7] of pointer to integer */ • int (*p)[7]; /* p is pointer to array[7] of integer */ • int **p; /* p is pointer to pointer to integer */ • void f(); /* f is function returning void */ • void *f(); /* f is function returning pointer to void */ • void (*fp)(); /* fp is pointer to function returning void */ • void *(*fp)(); /* fp is pointer to function returning pointer to void */ • Void (*fp[7])(); /* fp is array[7] of pointer to function returning void */ • 힌트 : • 는 []나 ()보다 우선 순위가 늦음.
포인터 이해 (2) • 형변환 long al = 0x00001234; Short bl; bl = (short)al; int a[5]; int (*p)[5]; p = (int (*)[5])a;
배열과 포인터 (1) int a[3][5]; a[i][j]; *(a[i] + j); (*(a+i))[j]; *((*(a+i)) + j) *(&a[0][0] + 5*i +j)
배열과 포인터 (2) • 함수 인자로서의 배열 int sum(int (*a)[5]) { int i, j, sum = 0; for(i=0; i < 3; i++) for(j=0; j < 5; j++) sum += a[i][j] return sum; } int sum(int a[][5]) { int i, j, sum = 0; for(i=0; i < 3; i++) for(j=0; j < 5; j++) sum += a[i][j] return sum; } int b[][5] = {1,2,3, …}; c = sum(b); /* C-스타일 */ c = sum((int (*)[5])b); /*C++스타일*/ int sum(int a[][5]) int sum(int a[3][5]) int sum(int (*a)[5])
배열과 포인터 (3) • 기본적으로 배열과 포인터는 동일한 인터페이스 • 3차원 배열 int sum(int a[][5][7]) int sum(int a[3][5][7]) int sum(int (*a)[5][7]) a[i][j][k] == *(&a[0][0][0] + 5*7*i + 7*j +k)
char * const char *p = “constant”; p[0] = ‘d’; /* not possible */ char *p = “constant”; p[0] = ‘d’; /* not possible */ const qualifier(한정어) : 상수처럼 취급하게 해줌. 즉 변수의 값이 변하지 않아야 한다는 것을 명시적으로 지정해 준다.
char ** (1) void swapstrings(char *l, char *r) { char *t; t = l; l = r; r = t; } char *l, *r; l = “left”; r = “right”; swapstrings(l, r); l r t l 맞게 교환되었을까? r
char ** (1) void swapstrings(char *l, char *r) { char *t; t = l; l = r; r = t; } char *l, *r; l = “left”; r = “right”; swapstrings(l, r); l r t l 맞게 교환되었을까? r
char ** (1) void swapstrings(char *l, char *r) { char *t; t = l; l = r; r = t; } char *l, *r; l = “left”; r = “right”; swapstrings(l, r); l r t l 맞게 교환되었을까? r
char ** (1) void swapstrings(char *l, char *r) { char *t; t = l; l = r; r = t; } char *l, *r; l = “left”; r = “right”; swapstrings(l, r); l r t l 맞게 교환되었을까? r
char ** (2) void swapstrings(char **l, char **r) { char *t; t = *l; *l = *r; *r = t; } char *l, *r; l = “left”; r = “right”; swapstrings(&l, &r); l r t l 맞게 교환되었을까? r
char ** (2) void swapstrings(char **l, char **r) { char *t; t = *l; *l = *r; *r = t; } char *l, *r; l = “left”; r = “right”; swapstrings(&l, &r); l r t l 맞게 교환되었을까? r
char ** (2) void swapstrings(char **l, char **r) { char *t; t = *l; *l = *r; *r = t; } char *l, *r; l = “left”; r = “right”; swapstrings(&l, &r); l r t l 맞게 교환되었을까? r
char ** (2) void swapstrings(char **l, char **r) { char *t; t = *l; *l = *r; *r = t; } char *l, *r; l = “left”; r = “right”; swapstrings(&l, &r); l r t l 맞게 교환되었을까? r
main 함수의 인자 전달 int main(int argc, char *argv[]) { … return 1; } C:\a.exe this is a final homework. a.exe this is a final homework
과제 (6월 10일 자정까지) • 프로그램 실행시 main 함수의 인자로 받은 문자열을 ASCII 순으로 정렬하여 출력하는 프로그램 작성 • 교재 6.13 참고 • 이메일 제출 • 소스코드 • 보고서
보고서 작성 요령 • 소스 코드 설명 • 정렬이 되는 과정을 설명 • 보고서 채점 비중 높음 • 6월 11일 기말 고사에서는 과제와 관련된 내용 출제될 예정