제14장 포인터 활용

Download Report

Transcript 제14장 포인터 활용

쉽게 풀어쓴 C언어 Express
제14장 포인터 활용
© 2012 생능출판사 All rights reserved
이번 장에서 학습할 내용
•
•
•
•
•
•
이중 포인터
포인터 배열
배열 포인터
함수 포인터
다차원 배열과 포인터
main 함수 인자
© 2012 생능출판사 All rights reserved
여러 가지 포인터
활용 방법과 main
함수의 인자에 대해
학습합니다.
이중 포인터
 이중 포인터: 포인터를 가리키는 포인터
int i = 10;
int *p = &i;
int **q = &p;
// i는 int형 변수
// p는 i를 가리키는 포인터
// q는 포인터 p를 가리키는 이중 포인터
© 2012 생능출판사 All rights reserved
이중 포인터
#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;
printf("i=%d *p=%d **q=%d \n", i, *p, **q);
}
return 0;
© 2012 생능출판사 All rights reserved
i=200
*p=200
**q=200
i=300
result**q=300
*p=300
이중 포인터
#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;
}
All that glisters is not gold.
result
© 2012 생능출판사 All rights reserved
포인터 배열
int a = 10, b = 20, c = 30, d = 40, e = 50;
int *pa[5] = { &a, &b, &c, &d, &e };
© 2012 생능출판사 All rights reserved
문자열 배열: 2차원 문자 배열
char fruits[ ][10] = {
"apple",
"blueberry",
"orange",
"melon"
};
2차원 배열을 사
용하면 낭비되는
공간이 생성되죠.
a
p
p
l
e \0
b
l
u
e
b
e
o
r
a
n
g
e \0
m
e
l
o
n \0
© 2012 생능출판사 All rights reserved
r
r
y \0
낭비되는
공간!
문자열 배열: 문자 포인터 배열
char *fruits[ ] = {
"apple",
"blueberry",
"orange",
"melon"
};
fruits[0]
a
p
p
l
e \0
b
l
u
e
b
e
o
r
a
n
g
e \0
m
e
l
o
n \0
r
fruits[1]
fruits[2]
fruits[3]
© 2012 생능출판사 All rights reserved
r
y \0
문자열 배열
#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;
© 2012 생능출판사 All rights reserved
fruits[0]
fruits[1]
a
p
p
l
e
\0
b
l
u
e
b
e
r
o
r
a
n
g
e
\0
m e
l
o
n
\0
fruits[2]
fruits[3]
apple
result
blueberry
orange
melon
r
y
\0
배열 포인터
#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;
pa
pa+1
a
1
2
3
4
5
6
7
8
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]) { … }
printf("%d %d\n", (*pa)[2], pa[0][2]);
printf("%d %d\n", (*(pa + 1))[2], pa[1][2]);
}
© 2012 생능출판사 All rights reserved
3
7
3
7
3
re
7
s
3
7ul
t
함수 포인터
 함수 포인터(function pointer): 함수를 가리키는 포인터
 배열처럼 함수 이름도 함수를 가리키는 포인터로 사용 가능
int add(int, int);
int sub(int, int);
// 함수 원형
// 함수 원형
int (*pf)(int, int);
// 함수 포인터 변수
pf = add;
result = (*pf)(10, 20);
// pf  add()
// 함수 포인터를 통하여 함수 호출: add(10, 20)
pf = sub;
result = pf(10, 20);
// pf  sub()
// 함수 포인터를 통하여 함수 호출: sub(10, 20)
int *f(int, int);
// 함수 원형
// int* 반환
int add(int a, int b) { return a + b; }
pf
int sub(int a, int b) { return a - b; }
© 2012 생능출판사 All rights reserved
함수 포인터
#include <stdio.h>
int add(int, int);
int sub(int, int);
int main(void) {
int (*pf)(int, int);
int result;
int add(int x, int y) {
return x + y;
}
int sub(int x, int y) {
return x - y;
}
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;
© 2012 생능출판사 All rights reserved
10 + 20 = 30
10 - 20 = result
-10
함수 포인터 배열
printf("2개의 정수를 입력하시오: ");
scanf("%d %d", &x, &y);
#include <stdio.h>
void menu(void);
int add(int x, int y);
int sub(int x, int y);
int mul(int x, int y);
int div(int x, int y);
int main(void) {
int choice, result, x, y;
int (*pf[4])(int, int) =
{ add, sub, mul, div };
while (1) {
menu();
printf("메뉴를 선택하시오: ");
scanf("%d", &choice);
if (choice < 0 || choice >=4) break;
© 2012 생능출판사 All rights reserved
}
}
result = pf[choice](x, y);
printf("연산 결과 = %d\n", result);
return 0;
int add(int a, int b) { … }
pf[0]
pf[1]
int sub(int a, int b) { … }
pf[2]
int mul(int a, int b) { … }
pf[3]
int div(int a, int b) { … }
함수 포인터 배열
void menu(void) {
printf("=====================\n");
printf("0. 덧셈\n");
printf("1. 뺄셈\n");
printf("2. 곱셈\n");
printf("3. 나눗셈\n");
printf("4. 종료\n");
printf("=====================\n");
}
int
int
int
int
add(int
sub(int
mul(int
div(int
x,
x,
x,
x,
int
int
int
int
y)
y)
y)
y)
{
{
{
{
© 2012 생능출판사 All rights reserved
return
return
return
return
x
x
x
x
+
*
/
y;
y;
y;
y;
}
}
}
}
=====================
0. 덧셈
1. 뺄셈
2. 곱셈
result
3. 나눗셈
4. 종료
=====================
메뉴를 선택하시오: 2
2개의 정수를 입력하시오: 10 20
연산 결과 = 200
=====================
0. 덧셈
1. 뺄셈
2. 곱셈
3. 나눗셈
4. 종료
=====================
메뉴를 선택하시오: 4
함수 포인터 인자
#include <stdio.h>
#include <math.h>
typedef double (*T_PF)(double);
void map(double a[], int n, T_PF pf);
void out(const double a[], int n);
double square(double v);
double increase(double v);
int main() {
double a[] = { 1.0, 2.0, 3.0, 4.0 };
int n = sizeof a / sizeof a[0];
out(a,
map(a,
map(a,
map(a,
n);
n, square); out(a, n);
n, sqrt); out(a, n);
n, increase); out(a, n);
return 0;
}
© 2012 생능출판사 All rights reserved
void map(double a[], int n, T_PF pf) {
int i;
for (i = 0; i < n; i++)
a[i] = (*pf)(a[i]);
}
void out(const double a[], int n) {
int i;
printf("[%d]", n);
for (i = 0; i < n; i++)
printf(" %g", a[i]);
putchar('\n');
}
double square(double v) {
return v * v;
}
double increase(double v) {
return v + 1.0;
[4] 1 2 3 4
}
[4] 1 4result
9 16
[4] 1 2 3 4
[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];


m
pa
(m)
 *(p+1)  p[1]  m[0][1]
sizeof m: 3 * 4 * 4 = 48
sizeof m[0]: 4 * 4 = 16
p
pa+1
(m+1)
pa+2
(m+2)
m[0]
m[1]
m[2]
p+2
p+3
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[0][0] m[0][1] m[0][2] m[0][3]
m[1][0] m[1][1] m[1][2] m[1][3]
© 2012 생능출판사 All rights reserved
p+1
m[2]
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]);
© 2012 생능출판사 All rights reserved
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
#define NC
3
4
int main(void) {
int m[NR][NC] = {
{ 0, 1, 2, 3 },
{ 10, 11, 12, 13 },
{ 20, 21, 22, -1 }
};
m[1][2] = 12
=== 3 x 4 ===
result
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
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;
}
© 2012 생능출판사 All rights reserved
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("=============");
}
© 2012 생능출판사 All rights reserved
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;
}
© 2012 생능출판사 All rights reserved
void 포인터
 어떤 타입이라도 가리킬 수 있는 포인터




대상체의 타입이 정해져 있지 않음
예: void *pv;
T *  void * : 항상 허용
void *  T * : 위험; C: warning; C++: error
int a[5];
int *p = a;
void *pv = a; // int *  void *
p++
pv++
// O
// X
*p = 1
// O
*pv = 1
// X
*(int*)pv = 1 // O, void *  int *
© 2012 생능출판사 All rights reserved
((int*)pv)++ // O
(int*)pv++
// X, (int*)(pv++)
sizeof *p
sizeof *pv
sizeof pv
// sizeof(int) = 4
// X
// 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;
© 2012 생능출판사 All rights reserved
main 함수의 인자

main 함수는 명령행 인자(command line argument)를 전달 받을 수 있음
int main(int argc, char *argv[ ]) { … }
// argc(argument count): 인자 수, 프로그램 이름 포함
// argv(argument vector): 인자 리스트
C:\CP> mycopy src dst
argc
argv
argv
mycopy
3
src
dst
NULL
© 2012 생능출판사 All rights reserved
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
© 2012 생능출판사 All rights reserved
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!
Hello! C Programming
© 2012 생능출판사 All rights reserved
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입니다.
© 2012 생능출판사 All rights reserved