쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express
여러 가지 포인터 활용 방법과 main 함수의 인자에 대해 학습합니다. 이번 장에서 학습할 내용 여러 가지 포인터 활용 방법과 main 함수의 인자에 대해 학습합니다. 이중 포인터 포인터 배열 배열 포인터 함수 포인터 다차원 배열과 포인터 main 함수 인자
이중 포인터 이중 포인터: 포인터를 가리키는 포인터 int i = 10; // i는 int형 변수 int *p = &i; // p는 i를 가리키는 포인터 int **q = &p; // q는 포인터 p를 가리키는 이중 포인터
이중 포인터 result #include <stdio.h> int main(void) { int i; int *p = &i; int **q = &p; *p = 200; printf("i=%d *p=%d **q=%d \n", i, *p, **q); **q = 300; return 0; } i=200 *p=200 **q=200 result i=300 *p=300 **q=300
이중 포인터 result #include <stdio.h> void set_pointer(char **q); int main(void) { char *p; set_pointer(&p); printf("%s\n", p); return 0; } void set_pointer(char **q) { static char *proverb = "All that glisters is not gold."; *q = proverb; result All that glisters is not gold.
포인터 배열 int a = 10, b = 20, c = 30, d = 40, e = 50; int *pa[5] = { &a, &b, &c, &d, &e };
문자열 배열: 2차원 문자 배열 char fruits[ ][10] = { "apple", "blueberry", "orange", "melon" };
문자열 배열: 문자 포인터 배열 char *fruits[ ] = { "apple", "blueberry", "orange", "melon" };
문자열 배열 result #include <stdio.h> int main(void) { char *fruits[ ] = { "apple", "blueberry", "orange", "melon" }; int i, n = sizeof fruits / sizeof fruits[0]; for (i = 0; i < n; i++) printf("%s\n", fruits[i]); return 0; } fruits[0] fruits[1] fruits[2] fruits[3] m e l o n \0 r a g b u p y apple blueberry orange melon result
배열 포인터 pa pa+1 a result #include <stdio.h> void f(int (*pa)[4]); int main(void) { int a[2][4] = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 } }; int (*pa)[4] = a; printf("%d %d\n", (*pa)[2], pa[0][2]); printf("%d %d\n", (*(pa + 1))[2], pa[1][2]); f(a); return 0; } void f(int (*pa)[4]) { // void f(int pa[ ][4]) { … } a pa pa+1 1 2 3 4 5 6 7 8 3 3 7 7 result
함수 포인터 함수 포인터(function pointer): 함수를 가리키는 포인터 int *f(int, int); 배열처럼 함수 이름도 함수를 가리키는 포인터로 사용 가능 int add(int, int); // 함수 원형 int sub(int, int); // 함수 원형 int (*pf)(int, int); // 함수 포인터 변수 pf = add; // pf add() result = (*pf)(10, 20); // 함수 포인터를 통하여 함수 호출: add(10, 20) pf = sub; // pf sub() result = pf(10, 20); // 함수 포인터를 통하여 함수 호출: sub(10, 20) int *f(int, int); // 함수 원형 // int* 반환 pf int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; }
함수 포인터 result #include <stdio.h> int add(int x, int y) { return x + y; int add(int, int); int sub(int, int); int sub(int x, int y) { int main(void) { return x - y; int (*pf)(int, int); int result; pf = add; result = (*pf)(10, 20); printf("10 + 20 = %d\n", result); pf = sub; result = pf(10, 20); printf("10 - 20 = %d\n", result); return 0; } result 10 + 20 = 30 10 - 20 = -10
함수 포인터 배열 #include <stdio.h> printf("2개의 정수를 입력하시오: "); void menu(void); int add(int x, int y); scanf("%d %d", &x, &y); int sub(int x, int y); int mul(int x, int y); result = pf[choice](x, y); int div(int x, int y); printf("연산 결과 = %d\n", result); int main(void) { } int choice, result, x, y; int (*pf[4])(int, int) = return 0; { add, sub, mul, div }; while (1) { menu(); printf("메뉴를 선택하시오: "); scanf("%d", &choice); if (choice < 0 || choice >=4) break; pf[0] int add(int a, int b) { … } int sub(int a, int b) { … } int mul(int a, int b) { … } int div(int a, int b) { … } pf[1] pf[2] pf[3]
함수 포인터 배열 result void menu(void) { printf("=====================\n"); } int add(int x, int y) { return x + y; } int sub(int x, int y) { return x - y; } int mul(int x, int y) { return x * y; } int div(int x, int y) { return x / y; } result ===================== 0. 덧셈 1. 뺄셈 2. 곱셈 3. 나눗셈 4. 종료 메뉴를 선택하시오: 2 2개의 정수를 입력하시오: 10 20 연산 결과 = 200 메뉴를 선택하시오: 4
함수 포인터 인자 result #include <stdio.h> void map(double a[], int n, T_PF pf) { #include <math.h> int i; for (i = 0; i < n; i++) typedef double (*T_PF)(double); a[i] = (*pf)(a[i]); void map(double a[], int n, T_PF pf); void out(const double a[], int n); void out(const double a[], int n) { double square(double v); double increase(double v); printf("[%d]", n); int main() { printf(" %g", a[i]); double a[] = { 1.0, 2.0, 3.0, 4.0 }; putchar('\n'); int n = sizeof a / sizeof a[0]; out(a, n); double square(double v) { map(a, n, square); out(a, n); return v * v; map(a, n, sqrt); out(a, n); map(a, n, increase); out(a, n); double increase(double v) { return v + 1.0; return 0; } result [4] 1 2 3 4 [4] 1 4 9 16 [4] 2 3 4 5
다차원 배열과 포인터 int m[3][4]; 행 우선 순서(row major ordering)로 메모리에 저장 1행 2행 3행 int (*pa)[4] = m; *(pa+1) pa[1] m[1] pa[1][2] m[1][2] int *p = m[0]; *(p+1) p[1] m[0][1] sizeof m: 3 * 4 * 4 = 48 sizeof m[0]: 4 * 4 = 16 p p+1 p+2 p+3 m pa (m) m[0] pa+1 (m+1) m[1] pa+2 (m+2) m[2] m[0][0] m[0][1] m[0][2] m[0][3] m[1][0] m[1][1] m[1][2] m[1][3] m[2][0] m[2][1] m[2][2] m[2][3] m[0] m[1] m[2] m[0][0] m[0][1] m[0][2] m[0][3] m[1][0] m[1][1] m[1][2] m[1][3] m[2][0] m[2][1] m[2][2] m[2][3]
다차원 배열과 포인터 #include <stdio.h> int main(void) { int m[3][4]; int (*pa)[4] = m; int *p = m[0]; printf("m = %p\n", m); // int (*)[4] printf("m[0] = %p\n", m[0]); // int * printf("m[1] = %p\n", m[1]); // int * printf("&m[0][0] = %p\n", &m[0][0]); // int * printf("&m[1][0] = %p\n", &m[1][0]); // int * printf("pa = %p\n", pa); // int (*)[4] printf("pa+1 = %p\n", pa+1); // int (*)[4] printf("p = %p\n", p); // int * printf("p+1 = %p\n", p+1); // int * printf("sizeof m = %d\n", sizeof m); printf("sizeof m[0] = %d\n", sizeof m[0]); printf("sizeof *pa = %d\n", sizeof *pa); printf("sizeof *p = %d\n", sizeof *p); printf("sizeof pa[0] = %d\n", sizeof pa[0]); printf("sizeof p[0] = %d\n", sizeof p[0]); printf("sizeof pa = %d\n", sizeof pa); printf("sizeof p = %d\n", sizeof p); return 0; } m = 0012FF08 m[0] = 0012FF08 m[1] = 0012FF18 &m[0][0] = 0012FF08 &m[1][0] = 0012FF18 pa = 0012FF08 pa+1 = 0012FF18 p = 0012FF08 p+1 = 0012FF0C sizeof m = 48 sizeof m[0] = 16 sizeof *pa = 16 sizeof *p = 4 sizeof pa[0] = 16 sizeof p[0] = 4 sizeof pa = 4 sizeof p = 4
2D 배열 1D 배열 #include <stdio.h> int *get(int m[], int nc, int r, int c); void out(const int m[], int nr, int nc); int sum_row(const int a[], int n); int sum_col(const int m[], int nr, int nc, int c); int sum_all(const int m[], int nr, int nc); #define NR 3 #define NC 4 int main(void) { int m[NR][NC] = { { 0, 1, 2, 3 }, { 10, 11, 12, 13 }, { 20, 21, 22, -1 } }; printf("m[1][2] = %d\n", *get((int*)m, NC, 1, 2)); *get((int*)m, NC, 2, 3) = 23; out((int*)m, NR, NC); printf("sum of m[1][*] = %d\n", sum_row(m[1], NC)); printf("sum of m[*][2] = %d\n", sum_col((int*)m, NR, NC, 2)); printf("sum of m[*][*] = %d\n", sum_all((int*)m, NR, NC)); return 0; } result m[1][2] = 12 === 3 x 4 === 0 1 2 3 10 11 12 13 20 21 22 23 ============= sum of m[1][*] = 46 sum of m[*][2] = 36 sum of m[*][*] = 138
2D 배열 1D 배열 // return &m[r][c] int *get(int m[], int nc, int r, int c) { return m + (r * nc + c); } // output m[nr][nc] void out(const int m[], int nr, int nc) { const int *end = m + (nr * nc), *endr; printf("=== %d x %d ===\n", nr, nc); do { endr = m + nc; do { printf(" %2d", *m); } while (++m < endr); putchar('\n'); } while (m < end); puts("============="); }
2D 배열 1D 배열 // return sum of a[n] int sum_row(const int a[], int n) { const int *end = a + n; int sum = 0; do { sum += *a; } while (++a < end); return sum; } // return sum of column c in m[nr][nc] int sum_col(const int m[], int nr, int nc, int c) { const int *end = m + (nr * nc); int sum = 0; m += c; do { sum += *m; } while ((m += nc) < end); return sum; } // return sum of m[nr][nc] int sum_all(const int m[], int nr, int nc) { const int *end = m + (nr * nc); int sum = 0; do { sum += *m; } while (++m < end); return sum; }
void 포인터 어떤 타입이라도 가리킬 수 있는 포인터 대상체의 타입이 정해져 있지 않음 예: void *pv; T * void * : 항상 허용 void * T * : 위험; C: warning; C++: error int a[5]; int *p = a; void *pv = a; // int * void * p++ // O ((int*)pv)++ // O pv++ // X (int*)pv++ // X, (int*)(pv++) *p = 1 // O sizeof *p // sizeof(int) = 4 *pv = 1 // X sizeof *pv // X *(int*)pv = 1 // O, void * int * sizeof pv // sizeof(void*) = 4(8)
void 포인터 #include <stdio.h> int main(void) { int a[ ] = { 10, 20, 30, 40, 50 }; void *pv; pv = a; // 가능 pv = &a[2]; // 가능 *pv = 35; // 오류 pv++; // 오류 *(int*)pv = 35; // 가능 return 0; }
main 함수의 인자 main 함수는 명령행 인자(command line argument)를 전달 받을 수 있음 mycopy int main(int argc, char *argv[ ]) { … } // argc(argument count): 인자 수, 프로그램 이름 포함 // argv(argument vector): 인자 리스트 C:\CP> mycopy src dst argc 3 argv argv NULL mycopy src dst
mainarg #include <stdio.h> int main(int argc, char *argv[ ]) { int i; for (i = 0; i < argc; i++) printf("명령어 라인에서 %d번째 문자열 = %s\n", i, argv[i]); return 0; } c:\CP\mainarg\Debug>mainarg src dst 명령어 라인에서 0번째 문자열 = mainarg 명령어 라인에서 1번째 문자열 = src 명령어 라인에서 2번째 문자열 = dst
myecho #include <stdio.h> int main(int argc, char **argv) { while (*++argv) printf("%s ", *argv); putchar('\n'); return 0; } c:\CP\myecho\Debug>myecho Hello! C Programming Hello! C Programming
mile2km #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[ ]) { if (argc != 2) { printf("사용 방법: mile2km 거리\n"); return 1; } printf("입력된 거리는 %gkm입니다. \n", 1.609 * atof(argv[1])); return 0; c:\CP\mile2km\Debug>mile2km 10 입력된 거리는 16.09km입니다.