230 likes | 457 Views
메모리의 주소 (address) 메모리에는 일정 크기의 저장장소마다 위치를 나타내는 유일한 주소가 부여된다 . 주소 연산자 & 변수의 실제 메모리 주소를 구해줌 변수의 실제 메모리 주소를 출력 %p : 주소를 16 진수로 출력 %u : 주소를 10 진수로 출력. int age; scanf (“%d”, &age);. 12FF7C, 1310588. int age; printf (“%p, %u”, &age, &age); . 포인터 (pointer) p.280
E N D
메모리의 주소(address) • 메모리에는 일정 크기의 저장장소마다 위치를 나타내는 유일한 주소가 부여된다. • 주소 연산자 & • 변수의 실제 메모리 주소를 구해줌 • 변수의 실제 메모리 주소를 출력 • %p : 주소를 16진수로 출력 • %u : 주소를 10진수로 출력 int age; scanf (“%d”, &age); 12FF7C, 1310588 int age; printf (“%p, %u”, &age, &age);
포인터(pointer) p.280 자료가 저장된 주기억 장소의 주소를 저장하는 변수즉 특정 주기억 장소를 가리키는 데 사용되는 변수 일반 변수 var1 int var1; 메모리 100000번지 포인터 변수 ptr int * ptr; 500 (데이터) 100000 (번지) ptr=&var1; 포인터는 자신이 가리키는 주소를 몰라도 어떤 변수를 가리키는 지만 알고 있으면 충분히 코딩할 수 있으므로 일반적으론 다음과 같은 그림으로 표현한다. var1 500 ptr
포인터 선언 p.281 • 예) int var1=500; int * ptr; • 여러 포인터를 한꺼번에 선언하기 • int *ptr1, *ptr2, *ptr3; 자료형 * 포인터변수명; 포인터가 가리키는 곳에 저장된 자료의 형 int var1 int * ptr 500
포인터가 특정 변수를 가리키게 만들기 • 포인터에 가리킬 변수의 메모리 주소를 대입한다. 포인터 = &변수; • 예) int var1; int *ptr; var1=500; ptr = &var1; // 포인터 ptr이 변수 var1을 가리키게 함 • 포인터를 선언과 동시에 초기화하기 • int *ptr = &var1; 주) ptr(포인터) var1(변수): 12FF7C 번지 ptr(포인터) var1(변수): 12FF7C 번지 12FF7C 500 int * ptr; ptr=&var1; int * ptr; *ptr=&var1;
예제 10.1 void main( ) { char ch1 = 'A', ch2 = 'B'; char *ptr1, *ptr2; ptr1 = &ch1; ptr2 = &ch2; printf("\n변수 ch1의 주소 : %u 번지“ , ptr1); printf("\n변수 ch2의 주소 : %u 번지“ , ptr2); }
10.2 포인터와 관련된 연산 p.285 • 주소 연산자 & 변수의 실제 메모리 주소를 구해줌 ptr = &var1; • 간접 연산자(또는 역참조 연산자) * 포인터변수가 가리키는 기억장소를 의미 *포인터변수 ptr : ptr을 참조하라. *ptr : ptr에 저장된 주소에 해당하는 메모리를 참조하라. *ptr ptr 12FF7C 10 주) 실행문에서의 ‘*’는 포인터 선언의 *가 아닌 역참조를 의미 int * ptr; 포인터 선언 var = *ptr; 역참조
ptr n : 12FF7C 번지 n=10; ptr=&n; printf(“%d”,n); printf(“%p”, ptr); printf(“%d”,*ptr); 10 변수 n에 저장된 값 포인터 변수 ptr에 저장된 값 • 포인터 ptr에 저장된 주소에 해당하는 기억장소에 저장된 값 즉 ptr이 가리키는 기억장소에 저장된 값 • ptr을 통한 간접적인 n의 참조
간접 연산자(또는 역참조 연산자) * 대입문의 왼쪽 변수 l-value:기억장소 int * ptr = &n; n=10; n = n + 1 ; *ptr = *ptr + 1; printf(“%d”,n ); printf(“%d”,*ptr); n = n + 1 ; • 대입문 오른쪽의 변수 • r-value :기억장소(변수)에 저장된 값 ptr n : 12FF7C 번지 10 위의 결과 printf(“%d”,n ); 12 printf(“%d”,*ptr); 12 r-value (ptr이 가리키는 기억장소에 저장된 값)과 (1)을 더한 결과를 (ptr이 가리키는 기억장소)에 대입
출력 결과는? int sum =0; int *ptr1, *ptr2; // 선언 ptr1 = ∑ printf(“%d\n”, sum); printf(“%d\n”, *ptr1); printf(“%u\n”, &sum); printf(“%u\n”, ptr1); *ptr1= 1; printf(“%d\n”, *ptr1); *ptr1 = *ptr1 * 10; printf(“%d\n”, *ptr1); ptr2 = ptr1; (*ptr2)++; // *ptr2 = *ptr2+1; printf(“%d, %d\n”, *ptr1, *ptr2); ptr1 ptr2 sum : 100번지 0
fp sp first second temp 20 10 포인터 실습 • first, second의 내용을 int형 포인터 fp, sp를 이용하여교환하기 int first=20; int second=10; int *fp, *sp; 교환전의 first, second를출력하기 fp, sp를 이용 first, second 교환 교환후의 first, second 값을포인터 fp, sp를 이용출력
10.4 포인터와 함수 (인수 전달) • call by value • 함수가 호출될 때 가인수의 메모리가 할당되며 실인수의 값만 가인수에 전달되어 저장됨 • 함수 안에서 가인수의 값을 바꾸어도 함수 종료 후 호출한 곳으로 돌아 갔을 때 실인수의 값은 호출전과 같음 함수간의 독립성 보장 • call by address • 함수의 가인수로 포인터 변수를 이용하는 방식 • 함수가 호출될 때 가인수의 메모리(포인터로 4바이트)가 할당되며 실인수의 주소가 전달되어 저장됨 • 함수 안에서 가인수(포인터)를 이용하여 실인수의 내용을 변경할 수 있다. • 친구에게 수업 노트를 빌려줄 때 • 노트 원본을 빌려주는 것 (주소호출)노트를 복사하여 복사본을 갖게 하는 것 (값 호출)
call by address 함수명( 실인수의 주소 ) • 함수 호출시 int a = 10; func(&a); a를 출력하면? • 함수 정의시 void func(int * ptr) { *ptr = 20; } a 10 12FF78번지 리턴형 함수명( 자료형 * 가인수 ) { 함수 본체 } ptr 12FF78 실인수의 자료형과 동일
100 200 a b x y p.298 예제 10.10 주소에 의한 호출(call by address):두 변수의 값 교환 * * 책 수정하기 void int_swap(int __ x, int __ y ); //원형 선언 void main( ) { int a=100, b=200; printf(“교환전: %d, %d \n”, a, b); int_swap(___a, ___b); printf(“교환후: %d, %d \n”, a, b); } void int_swap(int ___ x, int ___ y) { int temp; temp = ___x; ___x = ___y; ___y = temp; } & & * * * * * * temp
배열명 intvalue[N] = {90, 80, 70, 90, 100}; division(value); for (i=0; i<N; i++) printf(“%d”, value[i]); void division( intary[N]) { inti; for (i=0; i<5; i++) ary[i] = ary[i]/10; } 결과는? • division 함수에서는 ary이름의 배열로서 사용하면 된다. main 함수와 같은 기억공간을 공유하게 되므로 division에서 배열 내용을 수정하고 main으로 돌아오면 main의 value 배열의 내용도 바꿔져 있게 된다.
value • 배열명은 배열의 첫번째 원소를 가리키는 포인터 int value[] = {90, 80, 70, 90, 100}; division(value); for (i=0; i<5; i++) printf(“%d”, value[i]); void division( int * ary) { inti; for (i=0; i<5; i++) ary[i] = ary[i]/10; } • division 함수에서는 ary를배열이름으로 사용하면 된다.
최대치는 max에 최대치의 배열 첨차는 index에 저장이 되게 하려면? • void main() { • int score[N] ={90,99,51,60,70}; • inti, max, index; • max=maximum(_________, &index); • printf("최대치: score[%d]=%d ", • index, max); • } #include <stdio.h> #define N 5 void main() { int score[N]={90,99,51,60,70}; inti, max, index; max= score[0]; index=0; for ( i=1 ; i< N ; i++) { if (max < score[i]) { max = score[i]; index = i; } } printf("최대치: score[%d]=%d ", index, max); } // 전달된 배열의 최대치는리턴하고 최대치의 // 배열 첨자는 main의 index에저장되도록 // index를 가리키는 포인터 which를 선언 intmaximum( 배열선언 , int *which ) { int max; *which = 0 ; //첨자를 0으로 초기화 : }
포인터 변수에는 사용자가 직접 주소를 저장할 수 없다. • NULL 상수는 예외 int *ptr = 10000; ---(X) int *ptr = NULL; ---(O) • NULL 상수 포인터의 초기화 값으로 주로 사용되며 포인터가 어떤 메모리도 가리키고 있지 않다는 의미로서 이용됨 char * ptr=NULL; : // 특정 학생의 이름을 찾아서 ptr이 가리키게 하는 코드 if ( ptr == NULL ) { printf(“ 그런 사람은 없습니다.”);
int * n 1 2 3 4 5 6 • 포인터 + 1 또는 포인터 -1 포인터의 ‘형’ 에 따라 증가(감소)되는 값이 달라진다. 즉 포인터가 가리키는 자료형이 실제로 메모리를 차지하는 크기만큼 증가됨 int형 포인터 4 double형 포인터 8 char형 포인터 1 n++ 후? n 형 *포인터; : 포인터++; 포인터는 바로 다음 자료가 저장된 장소를 가리키게 됨
95 88 76 54 85 82 • 배열명 • 배열의 첫번째 원소를 가리키는 포인터 • int point[] = {95, 88, 76, 54, 85, 82}; point에 저장된 100번지를 참조 (100+1·4)번지를 참조 point 100번지 • 결과는? • printf(“%d \n”, *point); • printf(“%d \n”, *(point+1)); • printf(“%d \n”, *(point+2)); 100(번지) 95 88 76 (100+2·4)번지를 참조
111 222 333 444 a 555 6 : int a[5] = {111, 222, 333, 444, 555 }; 7 : int *p = a; // int * p; p=1; 8 : int i; 15 : 16 : for(i=0; i<5; ++i) { 17 : printf(“ … %d, … %d", a[i], *(p+i) ); 19 : } 20 : p
value • 14번 슬라이드를 포인터 이용하여 수정하기 int value[] = {90, 80, 70, 90, 100}; division(value); for (i=0; i<5; i++) printf(“%d”, value[i]); void division ( int * ary) { inti; for (i=0; i<5; i++) *(ary+i) = *(ary+i) / 10; } 14번 슬라이드의 ary[i] = ary[i]/10;
포인터를 이용한 변수 내용 교환 fp=&first; sp=&second; temp = *fp; *fp = *sp; *sp = temp; • 이처럼 두 변수 first, second를 직접 이용하지 않고 포인터 fp, sp를 이용하여 두 변수의 내용을 간접적으로 참조하여 교환시킬 수 있다.
void main() { int n1 = 10, n2 = 20; int *ptr1, *ptr2, *temp; ptr1 = &n1; ptr2 = &n2; printf("%3d", n1); printf("%3d", *ptr1); n1 = 30; printf("%3d", n1); printf("%3d", *ptr1); *ptr1 = *ptr2 + 5; printf("%3d", n1); printf("%3d", *ptr1); temp = ptr1; ptr1 = ptr2; ptr2 = temp; n1 = 10; n2 = 20; printf("%3d", n1); printf("%3d", n2); printf("%3d", *ptr1); printf("%3d", *ptr2); }