오픈소스소프트웨어개발입문 (CP33992) 포인터 부산대학교공과대학정보컴퓨터공학부
학습목표 포인터선언과간접참조를통한포인터사용방법을알수있다. 함수의인수전달에서포인터의역할및사용방법을알수있다. 포인터를통한배열원소의참조방법에대해알수있다. 포인터의가감연산을통한다양한활용법을알수있다. 포인터를이용한문자열처리에대해알수있다. void 포인터, 함수포인터의사용방법을알수있다. 2
포인터선언과간접참조 3
메모리구조 컴퓨터메모리 메모리셀이연속적으로나열된형태 각메모리셀에는주소가부여되어있음 데이터는각데이터크기에필요한만큼메모리셀을차지함 메모리셀자체정보 어떤데이터 a가차지하는메모리셀개수는 sizeof(a) 로알수있음 메모리셀주소는? 4
포인터 (pointer) 란? 데이터를저장하기위해할당된메모리공간의주소 포인터상수 (pointer constant): 메모리주소값 포인터변수 (pointer variable): 주소값을저장할수있는변수 데이터에는자료형이연관되어있으므로포인터에도자료형이연관됨 예 : int 포인터, double 포인터등 5
간접참조 (indirection, dereferencing) 포인터가가리키는곳을따라가연관된데이터혹은그데이터가저장된공간을참조하는것 간접참조한데이터의자료형은포인터자료형을이용하여판단함 포인터 간접참조 int 포인터상수 1024 int 형데이터 double 포인터변수 1052 double 형데이터 6
포인터선언과사용 포인터선언형식 자료형 * 포인터변수 ; 포인터사용예 one 1234 int one = 1; int *to_one; to_one = &one; // int 변수 // int 포인터변수 // to_one 은 one 을가리킴 to_one one = one + 1; // one 2 one = *to_one + 1; // one 3 *to_one = one + 1; // one 4 포인터와일반변수를함께선언 int one, *to_one; 간접참조수식 *to_one 의의미는대입연산자의어느쪽에있느냐에따라정해짐 오른편 : to_one 이가리키는곳에저장된값 왼편 : to_one 이가리키는곳에할당된변수 (int 변수 ) int one, *to_one = &one; // 선언과함께초기화! 7
포인터제 1 법칙 포인터제 1 법칙 *(& a) a 포인터제 1 법칙의의미 주소연산을취한결과에간접참조연산을취하면원래변수와같음 234 1 a *(& a) &a 8
함수의인수전달 9
포인터를인수로전달하면 포인터인수전달 포인터를간접참조함으로써해당포인터가가리키는데이터값을변경할수있음 호출된함수에서호출한함수의변수값을변경할수도있음 포인터인수전달을사용하는이유 호출된함수의 부수효과 (side-effect) 로서호출한함수의변수값을변경하기위해 인수로전달할데이터의크기가매우큰경우에인수전달효율을높이기위해 인수데이터크기가큰경우의예 : 배열, 구조체 사실 C에서배열은항상포인터를통해전달됨 [ 프로그램 11-1] 두변수값교환프로그램 학습 point: swap 함수호출후 main 함수의지역변수 a와 b에저장된값이교환되지않는이유와교환하는방법을알수있음 10
프로그램 11-1 (1/2) swap1.c 이부분을함수로수정 swap0.c 교환되지않은이유? swap 의 a, b 는 main 의 a, b 가아니다. main 의 a, b 의사본일뿐이다. 11 swap2.c
프로그램 11-1 (2/2) 교환되는이유? swap 에서 main 의 a, b 의주소를알고있으므로이들변수값을변경할수있다. swap2.c 12
배열과포인터 13
배열이름과포인터 배열이름을포인터에저장할수있음 배열이름은배열이할당된공간의주소이므로포인터상수임 따라서배열이름을포인터변수에저장할수있음 이때, 포인터의타입은배열원소를가리킬수있는타입이어야함 [ 프로그램 11-2] 배열이름을포인터에저장할수있는지확인하는프로그램 (arraryname.c) 학습 point: char 형배열이름 msg를 char형포인터 p에저장할수있음 14
프로그램 11-2 char 형배열선언 char 형포인터선언및 char 형배열이름저장 15
포인터가감연산 포인터에가감연산을취하면포인터가가리키는자료의크기단위로포인터값이증감함 포인터가감연산예 : int a[10], *p = a; p += 2; 포인터 p 값은 2 만큼증가하는것이아니라 2 * sizeof(int) 만큼증가함 [ 프로그램 11-3] 포인터의증감결과를확인하는프로그램 (ptrincr.c) 학습 point: int 포인터 a 와 b 의증감연산시 a 와 b 에저장된주소값이 sizeof(int)*( 증 감값 ) 만큼증가함을알수있음 16
프로그램 11-3 포인터변수 a 와 b 의증감연산값을인자값으로갖는매크로함수 PRPTR 을호출 17
포인터를통한배열원소참조 배열첨자연산대신포인터간접참조연산을사용할수있음 [ 프로그램 11-4] 포인터를통해배열원소를참조함으로써문자열을출력하는프로그램 (printstr.c) 학습 point: 배열 lyrics의원소를이용한문자열출력방법을알수있음 배열원소를사용한문자열출력 배열원소참조를이용한문자열출력 18
포인터제 2 법칙 포인터제 2 법칙 p[n] *(p + n) 포인터제 2 법칙의의미 배열첨자연산은본질적으로포인터연산이다. [ 프로그램 11-4] 포인터와배열의첨자연산사이의법칙을확인하기위한프로그램 (law2.c) 학습 point: 포인터제2법칙을확인 19
프로그램 11-4 포인터변수 p 에배열의시작주소저장 포인터제 2 법칙은포인터상수 ( 배열이름 ) 에도똑같이적용됨 20
배열인수전달복습 배열형태로선언한매개변수에는배열이름 ( 포인터상수 ) 이전달되므로사실포인터임 배열매개변수선언시크기선언은중요하지않음 예 : Tp[250] Tp[3] Tp[] [ 프로그램 11-5] 포인터를통해배열원소를참조함으로써문자열을출력하는프로그램 (printstr.c) 학습 point: 포인터상수혹은변수를함수의매개변수로전달하고전달받은포인터값을이용하여문자열을출력할수있음 21
프로그램 11-5 배열형태지만사실은 char 포인터임 배열형태의 char 포인터를통해배열원소를참조 p 가가리키는원소가 ' 참 ' 이면반복. 즉 p 가가리키는원소가 '\0' 이아니면반복. 포인터상수값을함수의인수로전달 char 포인터를통해배열원소를참조 p 가가리키는원소를참조한후 p 를 1 증가시킴 22
더복잡한선언문 23
사용형태대로선언한다. C 선언문에내재된철학 선언문을다시살펴봅시다. int i, a[10], *p; i는 int형이므로정수를저장할수있다. i = 5; a에첨자연산을취한 a[ ] 형태는 int형이다. 그래서 a는 int 배열형이다. a[0] = 5; p에간접참조연산을취한 *p 형태는 int형이다. 그래서 p는 int 포인터형이다. *p = 5; 24
더복잡한선언문이해 포인터의배열 int *a[3], *pi; // *(a[3]) 과같음 a에첨자연산을취한 a[ ] 형태가 int 포인터이므로 a는포인터의배열이다. 배열포인터 int (*q)[3], ai[3]; q에간접참조연산을취한 *q 형태가 int 배열이므로 q는 int형배열에대한포인터다. 정수포인터의배열 q 25
포인터의포인터 포인터의포인터는포인터를가리킬수있는포인터임 [ 프로그램 11-6] 포인터의포인터사용법을예시하기위한프로그램 (ppi.c) 학습 point: 포인터의포인터인 ppi는포인터변수의주소값을저장함 26
프로그램 11-6 Int 포인터의포인터인 ppi 는 int 포인터인 pi 의주소값을저장함 i 값을 12345 로변경함 27
다양한포인터 28
void 포인터 void는 없음 (nothing) void* 는 아무것이나가리키는포인터 (pointer to anything) 범용포인터 (generic pointer) 라고부르기도함 void 포인터는간접참조할수없음 간접참조하려면명시적으로형변환을수행해야함 [ 프로그램 11-7] void 포인터를이용하여정수나부동소수점수를출력하는프로 그램 (genericprint.c) 학습 point: 간접참조하기위해명시적으로포인터 p 를명시적으로형변환하여출력함 29
프로그램 11-7 void 포인터매개변수로사용함으로써 int 형변수와 double 형변수의주소값을저장함 정수값을출력하기위해 int 포인터로명시적형변환 실수값을출력하기위해 double 포인터로명시적형변환 30
함수포인터 함수포인터 (function pointer) 란? 함수를가리키기위한포인터 함수포인터를이용하여함수를호출할수있음 함수포인터로함수를호출할때에는간접참조하지않아도됨 리턴타입뿐만아니라매개변수자료형도함수의타입에해당함 함수포인터활용예 int (*fp)(int); int add1(int x) { return x + 1; } void print(int x) { printf("%d", x); } int add(int x, int y) { return x + y; }... fp = add1; // print 는저장불가 ( 리턴타입이다름 ) two = fp(1); // add는저장불가 ( 매개변수타입이다름 ) // add1을호출하게됨 [ 프로그램 11-8] 함수포인터사용법을보여주는프로그램 (funptr.c) 학습 point 함수이름은함수의주소값 void 함수포인터 fp를이용하여함수의주소값을저장하고함수이름이다른 printoct와 printdec 함수를호출할수있음 31
프로그램 11-8 정수형매개변수 1 개를갖는함수를간접참조하기위한함수포인터 fp 를선언함 printoct 함수의시작주소 ( 함수이름 ) 를함수포인터 fp에대입함수포인터 fp를이용한함수 printoct 호출 printdec 함수의시작주소 ( 함수이름 ) 를함수포인터 fp에대입함수포인터 fp를이용한함수 printdec 호출 32