450 likes | 634 Views
멘토링 6 주차. 11.08.09. a[0]. a[1]. a[2]. a[3]. a[4]. a[5]. . o. l. e. l. H. p+4. p+5. p+1. p+2. p. p+3. 배열과 포인터. 배열명은 포인터 상수로 첫 번째 요소의 주소를 갖는다 . char a[6]; //a == &a[0] 포인터 변수에 배열이름 또는 배열요소의 주소를 대입하여 직접 배열의 요소를 제어할 수 있다 . char *p, *p3;
E N D
멘토링6주차 11.08.09
a[0] a[1] a[2] a[3] a[4] a[5] \0 o l e l H p+4 p+5 p+1 p+2 p p+3 배열과 포인터 • 배열명은 포인터 상수로 첫 번째 요소의 주소를 갖는다. char a[6]; //a == &a[0] • 포인터 변수에 배열이름 또는 배열요소의 주소를 대입하여 직접 배열의 요소를 제어할 수 있다. char *p, *p3; p = a; //배열명을 포인터변수에 대입 // p+i == &a[i], *(p+i); == a[i] p3 = &a[3]; //인덱스 3인 배열 요소의 주소 대입 char a[6] = “Hello”; char *p; p = a; a == &a[0] 주소(요소위치) : p+i == &a[i]; 포인터와배열 값(배열요소) : *(p+i) == a[i];
배열과 포인터의 관계 • 배열명과 포인터를 이용한 배열의 주소와 배열의 요소 접근 표현방법 [배열요소 표현] [주소표현] p[0] *(p) *(a) a[0] 100 &a[0] a p p[1] *(p+1) *(a+1) a[1] 101 &a[1] a+1 p+1 p[2] *(p+2) *(a+2) a[2] 102 &a[2] a+2 p+2 p[3] *(p+3) *(a+3) a[3] 103 &a[3] a+3 p+3 p[4] *(p+4) *(a+4) a[4] 104 &a[4] a+4 p+4 a[i] == p[i] == *(a+i) == *(p+i) &a[i] == &p[i] == (a+i) == (p+i) char a[5], *p; p = a; <배열명을 포인터로 사용시 주의사항> 배열이름은 포인터 상수이므로 포인터 값을 변경할 수는 없다. (a+1 가능, a++ 불가능) 포인터와배열
st[0] st[1] st[2] st[3] st[4] A B C D \0 문자열과 포인터 • 포인터 변수를 이용하여 문자열 선언 • 포인터를 이용하여 문자열을 구성하는 각 문자를 순차적으로 접근 char chary[]=“Happy Day”, *strptr=“Good Luck”; printf(“%s, %s\n”, chary, strptr) printf("chary=%p, strptr=%p\n", chary, strptr); #include <stdio.h> main(){ char *st="ABCD", *p; int i; p = st; //문자열(문자배열)의 시작주소를 포인터에 대입 for (i=0; i< 5; i++) printf("st[%d] = %c\n", i, st[i]); for (i=0; i< 5; i++) printf("*st = %c\n", *(st+i)); for (i=0; i< 5; i++) printf("*st = %c\n", *(p+i)); while (*p) //null 문자일 때까지 반복 printf("*p = %c\n", *p++); } st p 포인터와배열
o o H d a y p p G \0 \0 st1[5] st1[1] st1[2] st1[3] st1[4] st1[0] 문자배열과 문자열포인터 • 문자배열 • 배열의 크기만큼 공간이 할당되어 배열명에 시작주소 저장 (char st1[]=“Happy Day”) • 배열명은 포인터 상수 • 새로운 문자열의 대입 불가능 • 문자배열의 각 요소변경 가능 • 문자열 포인터 • 문자열의 시작주소를 가지는 포인터 변수 (char *st2=“Good”;) • 새로운 문자열로 대입 가능 • 문자열을 구성하는 각 문자에 대한 변경 불가능 st1 st2 포인터와배열
Hallym allym llym lym ym m 포인터와배열
12FF78 12FF79 b[0][0] b[0][1] b[2][0] b[3][1] b[3][0] b[2][1] b[1][1] b[0][0] b[0][1] b[1][0] 12FF7A b[1][0] b[1][1] 12FF7B b[2][1] b[2][0] 12FF7C b[3][1] b[3][0] 12FF7D 12FF7E 12FF7F 이차원 배열 • 이차원 배열의 요소는 행 우선으로 접근하여 일차원적으로 저장 • 이차원 배열 명은 이차원 배열의 첫 번째 요소의 주소를 가지는 포인터 상수 • 이차원 배열의 1차원 요소는 각 행의 시작 주소를 가지는 포인터 상수 char b[4][2]; //b == &b[0][0] b[0] b b == b[0] == &b[0][0] b[i] == &b[i][0] b[1] b[2] b[3] 포인터와배열
b[0][0] b[0][1] b[1][0] b[1][1] b[2][1] b[2][0] b[3][1] b[3][0] 각 행의 시작 주소 b[n][m] == *(p + (n*clos) + m) == *(b[n]+m) 이차원 배열과 포인터 • 이차원 배열의 시작주소를 포인터에 대입하여 일 차원과 동일하게 배열의 요소를 지정 char b[4][2], *p; p = b; // 이차원 배열의 시작주소를 포인터로 지정 [배열요소표현] [주소표현] *(p) *(b[0]) b[0][0] 100 &b[0][0] b[0] p *(p+1) *(b[0]+1) b[0][1] 101 &b[0][1] b[0]+1 p+1 *(p+2) *(b[1])b[1][0] 102 &b[1][0] b[1] p+2 *(p+3) *(b[1]+1) b[1][1] 103 &b[1][1] b[1]+1 p+3 …. *(p+7) *(b[3]+1)b[3][1] 107 &b[3][1] b[3]+1 p+7 포인터와배열
이차원 배열 요소 포인터와배열
p[0] p[1] p[2] i j k 100 200 300 포인터 배열 • 포인터들을 저장하는 배열 • 연속된 공간에 포인터를 저장하기 위한 구조 포인터와배열
st[0] st[1] st[2] “Hard Disk” “Floppy Disk” “CD Rom” 포인터와배열
포인터의 포인터 포인터 변수 9A BC 100 주소 값 변수 p1 p2 a = *p2 = **p1 6A .. 9A … BC 이중 포인터 • 포인터가 다른 포인터를 가리키는 형태 • 다중간접참조(Multiple indirection) 형태 • 선언방법 자료형 **포인터변수; • int **p1, *p2, a; • a = 100; • p2 = &a; • p1 = &p2 • **p1 = 123; 포인터와배열
b[0] b[1] b[2] b[3] b[0][0] b[0][1] b[1][0] b[1][1] b[2][1] b[2][0] b[3][1] b[3][0] 이차원 배열과 이중포인터 b b[0][0] b[0][1] b[1][0] b[1][1] b[2][0] b[2][1] b[3][0] b[3][1] b[0][0]= *b[0]=**b b[0][1] = *(b[0]+1) = *(*(b+0)+1) b[1][1] = *(b[1]+1) = *(*(b+1)+1) b[3][0] = *b[3] = **(b+3) *(*(b + n) + m) == b[n][m] 포인터와배열
0012FF60 0012FF60 1 0012FF60 0012FF60 1 0012FF64 10 0012FF68 0012FF68 2 0012FF6C 20 0012FF70 0012FF70 3 0012FF74 30 0012FF78 0012FF78 4 0012FF7C 40 1 10 2 20 3 30 4 40 포인터와배열
연습문제(1) • 문자열을 입력하여 문자열의 순서를 바꾸어 출력하는 프로그램 작성 (1)문자열명을 포인터 형태로 표현하여 각 문자 접근처리로 해결 (2)포인터변수를 이용하여 문자열의 각 문자 접근처리로 해결 포인터와배열
포인터를 이용한 함수 매개변수 • 함수의 매개변수로 배열이나 문자열을 사용하는 경우 포인터 형태로 전달 포인터와배열
/* aryfunction.c 계속 */ int sumary(int ary[], int SIZE) { int sum = 0, i = 0; for (i = 0; i < SIZE; i++) { sum += ary[i]; } return sum; } int sumaryp(int *ary, int SIZE) { int sum = 0, i = 0; for (i = 0; i < SIZE; i++) { sum += ary[i]; } return sum; } int sump(int *ary, int SIZE) { int sum = 0, i = 0; for (i = 0; i < SIZE; i++) { sum += *(ary + i); } return sum; } int sump2(int *ary, int SIZE) { int sum = 0, i = 0; for (i = 0; i < SIZE; i++) { sum += *ary++; } return sum; } 포인터와배열
2차원 배열을 매개변수로 사용 • 함수를 호출하는 부분 int ca[2][3]; …. f1(ca); //2차원 배열명을 실 매개변수로 사용 ….. • 함수정의 부분 (1) f1(int *ca) //1차원적으로 접근할 수 있는 포인터형식 (2) f1(int (*ca)[3]) //2차원적으로 접근할 수 있는 배열포인터 형식 (3) f1(int ca[][3]) (4) f1(int ca[2][3]) 포인터와배열
12FF70 … 12FF78 n 12FF7C 12FF80 n[1][2]=6 x = 12FF78 n[0][1]=2 n[0][2]=3 n[1][1]=5 n[0][0]=1 n[1][0]=4 … 12FF84 12FF88 12FF8C for (i=0; i< Rows*Cols; i++) *(x+i) *= *(x+i); 포인터와배열
/* aryfunction2.c 계속 */ int sumary(int ary[][Cols], int SIZE) { int sum = 0, i = 0, j=0; for (i = 0; i < SIZE; i++) { for (j = 0; j < Cols; j++) { sum += ary[i][j]; } } return sum; } int sumaryp(int (*ary)[Cols], int SIZE) { int sum = 0, i = 0, j=0; for (i = 0; i < SIZE; i++) { for (j = 0; j < Cols; j++) { sum += ary[i][j]; } } return sum; } int sump(int *ary, int SIZE) { int sum = 0, i = 0; for (i = 0; i < SIZE; i++) { sum += (*ary++); } return sum; } 포인터와배열
문자열을 매개변수로 사용 포인터와배열
문자열 배열을 매개변수로 사용 포인터와배열
main()함수의 매개변수 • 매개변수를 받기 위한 형식 int main(int argc, char **argv) int main(int argc, char *argv[]) • 각 매개변수의 내용 • int argc; • 입력된 매개변수의 갯수를 정수(int)값으로 저장 • char *argv[]; //== **argv • 문자열 배열 형식(포인터 배열) • 입력한 매개 변수들의 포인터를 저장 argv[0] - 실행파일명. argv[1] - 첫번째 매개변수의 내용. argv[2] - 두번째 매개변수의 내용. … 포인터와배열
FFE0 *argv[](**argv) 구조 C:\work>myview a.txt b.txt 포인터배열 명령행 인자 3000 FFE8 argv[2] 3000 b.txt FFE4 argv[1] 2000 2000 FFE0 argv[0] 1000 a.txt main()의 매개변수 1000 argv myview • argv : 명령행 인자 목록을 가진 포인터 배열을 가리키는 이중 포인터 포인터와배열
main()함수의 매개변수 사용 예 //main argument Test (mainargv.c) #include <stdio.h> int main(int argc, char **argv) { int i; for (i=0; i < argc; i++) { printf("argv[%d] = %s\n", i, argv[i]); } return 0; } <실행 결과> E:\samples\PointerAry\Debug> mainargv 한림대학교 컴퓨터공학과 홍길동 argv[0] = E:\samples\PointerAry\Debug> mainargv.exe argv[1] = 한림대학교 argv[2] = 컴퓨터공학과 argv[3] = 홍길동 포인터와배열
12FF7C 12FF78 12FF24 12FF28 50 70 12FF7C … 12FF78 a b x y Call By Reference 예 <출력결과> a(&a)=50(0012FF7C) b(&b)=70(0012FF78) *x(x)=50(0012FF7C) *y(y)=70(0012FF78) a=70 b=50 포인터와배열
연습문제(2) (1)문자열을 추출하는 함수구현 <함수원형> • void leftstr(const char *str, char *des, int num) : str의 왼쪽에서 num개 추출하여 des에 저장 • void rightstr(const char *str, char *des, int num) : str의 오른쪽에서 num개 추출하여 des에 저장 • void midstr(const char *str, char *des, int st, int num) : str의 st위치에서 num개 추출하여 des에 저장 <출력예시> >>문자열 입력 : hallym leftstr(st, st2, 3) = hal rightstr(st, st2, 3) = lym midstr(st, st2, 1, 3) = all 포인터와배열
함수포인터 • 함수의 시작 주소를 포함하는 포인터 • 함수포인터를 사용하여 함수 호출가능 • 함수의 매개변수로 함수포인터 사용 • 같은 원형을 가지는 여러 개의 함수주소를 배열에 저장하여 호출가능 포인터와배열
함수 포인터 덤 • C에서 지원해주는 정렬함수 qsort에 대하여 • void qsort(void *array, size_t number, size_t size, int (*comp)(const void *a, const void *b) ); • 여기서 빨간색, 함수포인터가 쓰이고 있음 • Qsort는 각 인자별로 • 1. 정렬할 배열, • 2. 정렬한 원소수, • 3. 각 원소의 크기, • 4. 비교할 방법 • 즉 비교할 방법을 프로그래머가 마음대로 정할 수 있다는 것
연습문제(3) • 성명과 주민번호를 입력하여 연령대에 맞는 서비스를 출력하는 프로그램 작성 • 입력 : 성명, 주민번호 • 처리조건 : (1)반복입력, 성명에 “quit”를 입력하면 종료 (2)연령대 처리 • ~6 세 : 서비스 지원 안 함 • 7~13세 : 초등서비스 • 14~16세 : 중등서비스 • 17~19세 : 고등서비스 • 20세~ : 일반서비스 • 함수구현: • 주민번호의 길이와 형식(8-7)을 확인하는 함수 int chkNumber(const char *num) • 연령에 해당하는 서비스 처리 함수 void service(const char *num) 포인터와배열
출력예시 • >>성명 입력 (종료 - quit) : 홍길동 • >>주민번호 입력 : 501011-1010111 • 501011 - 1010111 주민번호의 형식이 맞습니다. • >>당신은 올해 나이 57세 입니다. • [일반서비스] 입니다. • >>성명 입력 (종료 - quit) : 성춘향 • >>주민번호 입력 : 28-43923472-28928 • 28-439 2 3472-28 주민번호의 길이가 맞지 않습니다. • >>성명 입력 (종료 - quit) : 성춘향 • >>주민번호 입력 : $$$$$-0000000 • >>주민번호 입력 : $$$$$$-1010111 • $$$$$$ - 1010111 생년월일이 잘못되었습니다. • >>성명 입력 (종료 - quit) : quit • >>종료합니다 포인터와배열