C 프로그래밍프로젝트 Chap 13. 포인터와배열! 함께이해하기 2013.10.02. 오병우 컴퓨터공학과
13-1 포인터와배열의관계 Programming in C, 정재은저, 사이텍미디어. 9 장참조 ( 교재의 13-1 은읽지말것 ) 배열이름의정체 배열이름은 Compile 시의 Symbol 로서첫번째요소의주소값을나타낸다. Symbol 로서컴파일시에만유효함 실행시에는메모리에잡히지않음 ( 변수의이름과동일함 ) cf.) Pointer 는실행시메모리에할당됨 32 비트운영체제에서는 4 바이트할당 Department of Computer Engineering 2
13-1 포인터와배열의관계 실행결과 배열요소간주소값의크기는 4 바이트임을 알수있다 ( 모든요소가붙어있다는의미 ). Department of Computer Engineering 3
배열이름과포인터비교 Programming in C, 정재은저, 사이텍미디어. 9 장참조 ( 교재의 13-1 은읽지말것 ) 포인터처럼실행시에배열이름에해당하는메모리 ( 주소값저장 ) 가할당되는가? 배열이름 No: 포인터와달리실행시메모리에주소값을저장하기위한공간이할당되지않음 배열자체가할당됨 a 포인터 a int a[3]; 프로그램을짤때와컴파일시까지만사용되는 Symbol 임. 실행시에는 0x1000 이사용되며, 주소값을저장하는공간이별도로할당되지않음. 배열자체가할당됨 배열 할당 int a; 프로그램을짤때와컴파일시까지만사용되는 Symbol 임. 실행시에는 0x1000 이사용되며 int 저장을위한공간이할당됨 int *pa = &a; 프로그램을짤때와컴파일시까지만사용되는 Symbol 임. 실행시에는 0x2014 가사용되며주소값을저장하는공간이할당됨 pa Department of Computer Engineering 4
배열이름 13-1 포인터와배열의관계 int main(void) { int a[5]={0, 1, 2, 3, 4}; int b=10; } a=&b; //Error! a 는실행시에메모리에존재하지않음 Department of Computer Engineering 5
실습 배열이름을포인터처럼사용가능 실행결과 Department of Computer Engineering 6
실습 포인터를배열처럼활용가능 포인터에 index 활용가능 #include <stdio.h> int main(void) { int arr[3]={0, 1, 2}; int *ptr = arr; // &arr[0] 도동일함 arr } printf("%d, %d, %d \n", ptr[0], ptr[1], ptr[2]); return 0; Department of Computer Engineering 7
포인터연산이란? 13-2 포인터연산 포인터가저장한값을증가혹은감소시키는연산을의미 ptr1++; ptr1 += 3; --ptr1; ptr2=ptr1+2; 그럴수도있고아닐수도있음 ptr 의타입에따라다름 ptr=1000 일때, (ptr+1) 은 1001 일까? * 또는 / 연산은허용될까? 안됨 Department of Computer Engineering 8
포인터연산 13-2 포인터연산 포인터가가리키는대상의자료형에따라서증가및감소되는값이차이를지님 적절치않은초기화 왼편과같이포인터변수에저장된값을대상으로하는 증가및감소연산을진행할수있다. 실행결과 예제의실행결과를통해서다음사실을알수있다. int형포인터변수대상의증가감소연산시 sizeof(int) 의크기만큼값이증가및감소한다. double형포인터변수대상의증가감소연산시 sizeof(double) 의크기만큼값이증가및감소한다. type형포인터변수대상의증가감소연산시 sizeof(type) 의크기만큼값이증가및감소한다. Department of Computer Engineering 9
포인터연산을통한배열요소의접근 실행결과 int형포인터변수의값은 4씩증가및감소를하니, int형포인터변수가 int형배열을가리키면, int형포인터변수의값을증가및감소시켜서배열요소에순차적으로접근이가능하다. Department of Computer Engineering 10
포인터와배열을통해서얻을수있는결론 Department of Computer Engineering 11
13-3 문자열상수포인터 문자열표현방식의이해 배열기반의문자열변수 포인터기반의문자열상수 총 5 bytes 메모리할당 char str1[5] char str1[]="abcd"; char *str2="abcd"; 총 9 bytes 메모리할당 ( 포인터 4 bytes + 문자열 5 bytes) Department of Computer Engineering 12
13-3 문자열상수포인터 #include <stdio.h> int main() { char str1[5]="abcd"; char *str2="abcd"; // 문자열변수선언 // 문자열상수선언 printf("%s \n", str1); printf("%s \n", str2); str1[0]='x'; str2[0]='x'; // 문자열변수변경, OK // 문자열상수변경, Error 발생 printf("%s \n", str1); printf("%s \n", str2); } return 0; Department of Computer Engineering 13
13-3 문자열상수포인터 Try this! 이건상수! Data Segment (Section) 에잡힘 #include <stdio.h> int main(void) { char *str1 = "Good!"; char *str2 = "Good!"; char str3[10] = Good! ; 이건변수! Stack 에잡힘 이걸 char str2[] = Good! ; 로바꾸면? 그럼변수가됨! Stack 에잡힘 } printf("%d, %d, %d \n", str1, str2, str3); printf( %s, %s, %s \n, str1, str2, str3); return 0; The result depends on the compiler. Department of Computer Engineering 14
포인터배열 13-4 포인터배열 배열의요소로포인터를지니는배열 int* arr1[10]; double* arr2[20]; char* arr3[30]; 18 장에서배우게될 int (*arr1)[10]; 과서로다름 ( 이건배열을가리키는포인터 ) int 를가리키는포인터가 10 개있는배열 연산자우선순위를체크하자! Department of Computer Engineering 15
13-4 포인터배열 포인터배열예제 1 #include <stdio.h> int main(void) 0x5000 0x100 저장공간의크기는포인터이므로 4Bytes (in 32 bits OS) 0x100 { 0x200 int a=10, b=20, c=30; int* arr[3]={&a, &b, &c}; 0x300 0x200 printf("%d \n", *arr[0]); printf("%d \n", *arr[1]); printf("%d \n", *arr[2]); arr, arr[0], *arr[0] 혼동하지않도록의미에유의할것! 0x300 } return 0; 표현식내용값 arr int 를저장하는 arr 배열의시작주소 0x5000 arr[0] *arr[0] int 를저장하는 arr 배열의첫번째공간 (4Bytes) 에저장되어있는변수 (a) 의시작주소 (&a) int 를저장하는 arr 배열의첫번째공간 (4Bytes) 에저장되어있는변수 (a) 의시작주소에저장된값 (a) 0x100 10 Department of Computer Engineering 16
13-4 포인터배열 포인터배열예제 2: 문자열배열 #include <stdio.h> int main(void) { char* arr[3]={ "Fervent-lecture", "TCP/IP", "Socket Programming" }; printf("%s \n", arr[0]); printf("%s \n", arr[1]); printf("%s \n", arr[2]); return 0; } 원래, ( 문자열이아닌 ) 문자가저장된주소를가리키는포인터의배열 문자열의시작문자의주소를가리키고있음을알고있으므로 %s 를사용함 ( 원래타입대로문자라면 %c 를사용했어야함 ) 0x100 0x1000 0x2000 0x3000 원래, char * 는문자가저장된주소를가리키지만, 보통, char * 는문자열의시작주소를가리키는의미로주로사용됨 0x1000 0x2000 0x3000 Dept. of Computer Engineering 17
연습문제 포인터를이용해배열을조작해보자. 문자열을입력받아그길이를출력하는프로그램을작성하자. 이때, 널문자는길이에포함하지않으며, 길이를계산하는과정에서포인터를사용해야한다. 문자열을입력받아거꾸로뒤집은다음결과를출력하는프로그램을작성하자. 이때, 뒤집는과정은포인터를사용해야한다. Department of Computer Engineering 18