쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express Slide 1 (of 27)
포인터란? 포인터(pointer): 주소를 가지고 있는 변수 Slide 2 (of 27)
변수의 주소 변수의 주소를 계산하는 연산자: & 변수 i의 주소: &i Slide 3 (of 27)
변수의 주소 int main(void) { int i = 10; char c = 69; float f = 12.3; printf("i의 주소: %u\n", &i); // 변수 i의 주소 출력 printf("c의 주소: %u\n", &c); // 변수 c의 주소 출력 printf("f의 주소: %u\n", &f); // 변수 f의 주소 출력 return 0; } i의 주소: 1245024 c의 주소: 1245015 f의 주소: 1245000 Slide 4 (of 27)
포인터의 선언 포인터: 변수의 주소를 가지고 있는 변수 int i = 10; // 정수형 변수 i 선언 int *p = &i; // 변수 i의 주소가 포인터 p로 대입 Slide 5 (of 27)
다양한 포인터의 선언 char c = 'A'; // 문자형 변수 c float f = 36.5; // 실수형 변수 f double d = 3.141592; // 실수형 변수 d char *pc = &c; // 문자를 가리키는 포인터 pc float *pf = &f; // 실수를 가리키는 포인터 pf double *pd = &d; // 실수를 가리키는 포인터 pd Slide 6 (of 27)
간접 참조 연산자 간접 참조 연산자 *: 포인터가 가리키는 값을 가져오는 연산자 int i = 10; int *p = &i; printf("%d\n", *p); // 10이 출력된다. *p = 20; printf("%d\n", *p); // 20이 출력된다. Slide 7 (of 27)
간접 참조 연산자의 해석 간접 참조 연산자: 지정된 위치에서 포인터의 타입에 따라 값을 읽어 들인다. int *p = 8; // 위치 8에서 정수를 읽는다. char *pc = 8; // 위치 8에서 문자를 읽는다. double *pd = 8; // 위치 8에서 실수를 읽는다. Slide 8 (of 27)
포인터 예제 #1 #include <stdio.h> int main(void) { int i = 3000; int *p = &i; // 변수와 포인터 연결 printf("&i = %u\n", &i); // 변수의 주소 출력 printf("p = %u\n", p); // 포인터의 값 출력 printf("i = %d\n", i); // 변수의 값 출력 printf("*p = %d\n", *p); // 포인터를 통한 간접 참조 값 출력 return 0; } &i = 1245024 p = 1245024 i = 3000 *p = 3000 Slide 9 (of 27)
포인터 예제 #2 #include <stdio.h> int main(void) { char c = 'A'; // 문자형 변수 정의 int i = 10000; // 정수형 변수 정의 double d = 6.78; // 실수형 변수 정의 char *pc = &c; // 문자형 포인터 정의 및 초기화 int *pi = &i; // 정수형 포인터 정의 및 초기화 double *pd = &d; // 실수형 포인터 정의 및 초기화 (*pc)++; // 간접 참조로 1 증가 *pi = *pi + 1; // 간접 참조로 1 증가 *pd += 1; // 간접 참조로 1 증가 printf("c = %c\n", c); printf("i = %d\n", i); printf("d = %f\n", d); return 0; } *pc++라고 하면 안됨 c = B i = 10001 d = 7.780000 Slide 10 (of 27)
포인터 사용시 주의점 #1 포인터의 타입과 변수의 타입은 일치하여야 한다. #include <stdio.h> int main(void) { int i; double *pd; pd = &i; // 오류! double형 포인터에 int형 변수의 주소를 대입 *pd = 36.5; return 0; } Slide 11 (of 27)
포인터 사용시 주의점 #2 초기화가 안된 포인터를 사용하면 안된다. int main(void) { int *p; // 포인터 p는 초기화가 안되어 있음 *p = 100; // 위험한 코드 return 0; } Slide 12 (of 27)
포인터 사용시 주의점 #3 포인터가 아무것도 가리키고 있지 않는 경우에는 NULL로 초기화 포인터의 유효성 여부 판단이 쉽다. Slide 13 (of 27)
포인터의 증가는 일반 변수와는 약간 다릅니다. 가리키는 객체의 크기만큼 증가합니다. 포인터 연산 가능한 연산: 증가, 감소, 덧셈, 뺄셈 연산 증가 연산의 경우 증가되는 값은 포인터가 가리키는 객체의 크기 포인터 타입 ++연산후 증가되는값 char 1 short 2 int 4 float double 8 포인터의 증가는 일반 변수와는 약간 다릅니다. 가리키는 객체의 크기만큼 증가합니다. Slide 14 (of 27)
증가 연산 예제 // 포인터의 증감 연산 #include <stdio.h> int main(void) { char *pc; int *pi; double *pd; pc = (char *)10000; pi = (int *)10000; pd = (double *)10000; printf("증가 전 pc = %d, pi = %d, pd = %d\n", pc, pi, pd); pc++; pi++; pd++; printf("증가 후 pc = %d, pi = %d, pd = %d\n", pc, pi, pd); return 0; } 증가 전 pc = 10000, pi = 10000, pd = 10000 증가 후 pc = 10001, pi = 10004, pd = 10008 Slide 15 (of 27)
간접 참조 연산자와 증감 연산자 수식 의미 v = *p++ p가 가리키는 값을 v에 대입한 후에 p를 증가한다. // 포인터의 증감 연산 #include <stdio.h> int main(void) { int i = 10; int *pi = &i; printf("i = %d, pi = %p\n", i, pi); (*pi)++; *pi++; return 0; } i = 10, pi = 0012FF60 i = 11, pi = 0012FF60 i = 11, pi = 0012FF64 Slide 16 (of 27)
포인터와 배열 // 포인터와 배열의 관계 #include <stdio.h> int main(void) { int a[] = { 10, 20, 30, 40, 50 }; printf("&a[0] = %u\n", &a[0]); printf("&a[1] = %u\n", &a[1]); printf("&a[2] = %u\n", &a[2]); printf("a = %u\n", a); return 0; } &a[0] = 1245008 &a[1] = 1245012 &a[2] = 1245016 a = 1245008 Slide 17 (of 27)
포인터와 배열 // 포인터와 배열의 관계 #include <stdio.h> int main(void) { int a[] = { 10, 20, 30, 40, 50 }; printf("a = %u\n", a); printf("a + 1 = %u\n", a + 1); printf("*a = %d\n", *a); printf("*(a+1) = %d\n", *(a+1)); return 0; } a = 1245008 a + 1 = 1245012 *a = 10 *(a+1) = 20 Slide 18 (of 27)
포인터를 배열처럼 사용 // 포인터를 배열 이름처럼 사용 #include <stdio.h> int main(void) { int a[] = { 10, 20, 30, 40, 50 }; int *p; p = a; printf("a[0]=%d a[1]=%d a[2]=%d \n", a[0], a[1], a[2]); printf("p[0]=%d p[1]=%d p[2]=%d \n\n", p[0], p[1], p[2]); p[0] = 60; p[1] = 70; p[2] = 80; printf("p[0]=%d p[1]=%d p[2]=%d \n", p[0], p[1], p[2]); return 0; } a[0]=10 a[1]=20 a[2]=30 p[0]=10 p[1]=20 p[2]=30 a[0]=60 a[1]=70 a[2]=80 p[0]=60 p[1]=70 p[2]=80 Slide 19 (of 27)
포인터와 함수 C에서의 인수 전달 방법 값에 의한 호출: 기본적인 방법 참조에 의한 호출: 포인터 이용 Slide 20 (of 27)
swap() 함수 #1 변수 2개의 값을 바꾸는 작업을 함수로 작성 #include <stdio.h> void swap(int x, int y); int main(void) { int a = 100, b = 200; printf("main() a=%d b=%d\n",a, b); swap(a, b); return 0; } void swap(int x, int y) { int tmp; printf("swap() x=%d y=%d\n",x, y); tmp = x; x = y; y = tmp; } main() a=100 b=200 swap() x=100 y=200 swap() x=200 y=100 Slide 21 (of 27)
swap() 함수 #2 포인터를 이용 #include <stdio.h> void swap(int x, int y); int main(void) { int a = 100, b = 200; printf("main() a=%d b=%d\n",a, b); swap(&a, &b); return 0; } void swap(int *px, int *py) { int tmp; printf("swap() *px=%d *py=%d\n", *px, *py); tmp = *px; *px = *py; *py = tmp; } main() a=100 b=200 swap() *px=100 *py=200 swap() *px=200 *py=100 main() a=200 b=100 Slide 22 (of 27)
2개 이상의 결과를 반환 #include <stdio.h> // 기울기와 y절편을계산 int get_line_parameter(int x1, int y1, int x2, int y2, float *slope, float *yintercept) { if( x1 == x2 ) return -1; else { *slope = (float)(y2 - y1)/(float)(x2 - x1); *yintercept = y1 - (*slope)*x1; return 0; } int main(void) float s, y; if( get_line_parameter(3, 3, 6, 6, &s, &y) == -1 ) printf("에러\n"); else printf("기울기는 %f, y절편은 %f\n", s, y); 기울기와 y-절편을 인수로 전달 기울기는 1.000000, y절편은 0.000000 Slide 23 (of 27)
배열이 함수 인수인 경우 일반 변수 vs 배열 배열의 경우, 크기가 큰 경우에 복사하려면 많은 시간 소모 배열의 경우, 배열의 주소를 전달 // 매개 변수 x에 기억 장소가 할당된다. void sub(int x) { ... } // 매개 변수 b[]에 기억 장소가 할당되지 않는다. void sub(int b[], int n) { ... } Slide 24 (of 27)
예제 // 포인터와 함수의 관계 #include <stdio.h> void sub(int b[], int n); int main(void) { int a[3] = { 1,2,3 }; printf("%d %d %d\n", a[0], a[1], a[2]); sub(a, 3); return 0; } void sub(int b[], int n) b[0] = 4; b[1] = 5; b[2] = 6; 1 2 3 4 5 6 Slide 25 (of 27)
주의 함수가 종료되더라도 남아 있는 변수의 주소를 반환하여야 한다. 지역 변수의 주소를 반환하면 , 함수가 종료되면 사라지기 때문에 오류 int *add(int x, int y) { int result; result = x + y; return &result; } 지역 변수 result는 함수가 종료되면 소멸되므로 그 주소를 반환하면 안된다.!! Slide 26 (of 27)
Q & A Slide 27 (of 27)