3.포인터

35
C 언언언 언언언 (3) 언언언 언언 "언언언언언 언언언언" NHN NEXT 언언언 언언언언 언 언언언언언언 언언언 언언언 언언언 .

Upload: hoyoung-jung

Post on 17-Jan-2015

294 views

Category:

Documents


3 download

DESCRIPTION

 

TRANSCRIPT

Page 1: 3.포인터

C 언어와 포인터 (3)

포인터 학습

"완전학습을 지향하는" NHN NEXT 정호영

나눔고딕 및 나눔고딕코딩 글꼴을 설치해 주세요 .

Page 2: 3.포인터

오늘의 토픽

1. 함수에 배열을 건네주기2. 2 차원 배열과 포인터3. 문자열과 포인터4. 구조체와 포인터

Page 3: 3.포인터

0. TIP

Page 4: 3.포인터

짧은 팁 :

(*&) 또는 (&*) 는 상쇄되어 사라집니다 .

int main(void) { int a = 4; int *p = &a; printf("%d %d\n", *&a, a); printf("%p %p\n", &*p, p);}

Page 5: 3.포인터

이중 포인터 다시 보기

int x = 10;int *ptr = &x;int **pptr = &ptr;

Page 6: 3.포인터

이중 포인터 다시 보기

/

- * 는 연속해서 올 수 있지만 & 는 안 됩니다 .- 이것보다는 그림이 더 명확합니다 .

int x = 10;int *ptr = &x;int **pptr = &ptr;

/*1) pptr = &ptr, ptr = &x 2) pptr = &ptr = &&x ( 아님 ) 2) *pptr = *(&ptr) = ptr3) **pptr = **(&ptr) = *ptr = *(&x) = x = 10*/

Page 7: 3.포인터

배열과 포인터의 차이점

arr = &arr[0] = &*(arr +0) = arr 입니다 .이 때 arr 은 읽기 전용입니다 !

int arr[] = {0, 1, 2, 3, 4};int *ptr = arr;ptr = ptr + 1; //ok, *ptr = 1;arr = arr + 1; //error

Page 8: 3.포인터

1. 함수에 배열을 건네주기

Page 9: 3.포인터

예제 ) 크기가 n 인 int 배열에 0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오 .

Page 10: 3.포인터

예제 ) 크기가 n 인 int 배열에 0 ~ n – 1 까지값을 초기화하는 함수를 작성하고 테스트하시오 .

void setArray(int array[], int n) {}

int main(void) {int arr[10];setArray(arr, 10);for( int i = 0; i < 10; i++)

printf(“%d\n”, arr[i]);return 0;

}

Page 11: 3.포인터

배열과 포인터는 다릅니다 .int *a; 와 int a[]; 는 서로 다른 문장인데딱 한 경우에는 완전히 같습니다 .

언제 ?

Page 12: 3.포인터

int *a; 와 int a[]; 는 서로 다른 문장이지만parameter 안에서는 같습니다 .

void foo(int *a)= void foo(int a[])= void foo(int a[10])

마지막 줄의 숫자는 아무 의미가 없습니다 . 무시됩니다 .

Page 13: 3.포인터

1 차원 배열은 배열이 아니라 포인터로 넘겨주기 때문에

1) 자동으로 Call by Reference 가 된다 .2) 배열의 크기를 알 수 없다 .

2 의 이유로 C 언어에서는 배열의 크기를반드시 따로 전달해야 합니다 .

Page 14: 3.포인터

예제 ) 크기가 n 인 배열에 0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오 .

Page 15: 3.포인터

예제 ) 크기가 n 인 int 배열에 0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오 .

void setArray(int *array, int n) {for( int i = 0; i < n; i++)

array[i] = i;}

int main(void) {int arr[10];setArray(arr, 10);for( int i = 0; i < 10; i++)

printf(“%d\n”, arr[i]);return 0;

}

Page 16: 3.포인터

예제 ) 크기가 n 인 배열을 동적 할당으로 생성하고0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오 .

Page 17: 3.포인터

예제 ) 크기가 n 인 배열을 동적 할당으로 생성하고0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오 .

*array[i] 라고 하면 어떻게 될까요 ?

void setArray(int **array, int n) {*array = calloc(n, sizeof(int)); for( int i = 0; i < n; i++)

(*array)[i] = i;}

int main(void) {int *ptr;setArray(&ptr, 10);for( int i = 0; i < 10; i++)

printf(“%d\n”, (*ptr)[i]);return 0;

}

Page 18: 3.포인터

2. 2 차원 배열과 포인터

Page 19: 3.포인터

1. 메모리는 1 차원인데 2 차원 배열을 어떻게 저장할까요 ?

왜 00, 01, 02, 10, 11, 12 순서로 접근할까요 ? 00, 10, 01, 11, 02, 12 순서도 상관없지 않나요 ?

int arr[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };

int main(void) {int arr[2][3] = { { 0, 1, 2 },{ 3, 4, 5 } };for (int i = 0; i < 2; i++)

for (int j = 0; j < 3; j++) printf("%p\n", &arr[i][j]);

}

Page 20: 3.포인터

arr[m][n] 배열을 1 차원 포인터로 캐스팅하면

arr[m][n]; //m * n 배열

int *ptr = (int *) arr;

라면…

arr[i][j]= *(ptr + i * n + j)

Page 21: 3.포인터

예제 ) 2 차원 배열과 단일 포인터

int main(void) {int arr[2][3] = { { 0, 1, 2 },{ 3, 4, 5 } };// int *ptr = arr; warning!!int *ptr = (int *) arr;for (int i = 0; i < 2; i++){

for (int j = 0; j < 3; j++) {printf("%d ", *(ptr + i * 3 + j));

}printf("\n");

}}

Page 22: 3.포인터

앞의 예제에서 알 수 있는 것처럼이차원 배열과 단일 포인터는 서로 다른 타입입니다 .그럼 이차원 배열의 이름은 어떤 타입의 주소일까요 ?

int

조금 복잡하지만 - ptr 변수는 int 3 개짜리 배열의 포인터입니다 .-이차원 배열은 1 차원 배열의 배열이다 .

int arr[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };int (*ptr)[3] = arr; //ok

Page 23: 3.포인터

예제 ) 2 차원 배열과 배열의 포인터

int main(void) {int arr[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } };for (int i = 0; i < 2; i++){

for (int j = 0; j < 3; j++) {printf("%d ", *(*(arr + i) + j));

}printf("\n");

}}

Page 24: 3.포인터

arr[i][j]= (*(arr+ i))[j]= *(*(arr +i) + j)

원리는 이런데 쓸모는 없습니다 .

Page 25: 3.포인터

함수로 이차원 배열을 전달하려면

1. 단일 포인터로 캐스팅해서 전달 또는2. 배열의 포인터로 전달

두 가지 방법이 있습니다 .

Page 26: 3.포인터

예제 )n * 5 이차원 배열을 엣지있게 출력하는 함수를 작성하세요 .

void print2d_arr(int(*arr)[5], int w) {for (int i = 0; i < w; i++){

for (int j = 0; j < 5; j++) {printf("%d ", arr[i][j]);

}printf("\n");

}}int main(void) {

int arr[3][5] = { { 0, 1, 2, 3, 4 }, { 5, 6, 7 }, { 8, 9 } };

print2d_arr(arr, 3);}

Page 27: 3.포인터

3. 문자열과 포인터

Page 28: 3.포인터

문자열은 그냥 문자의 1 차원 배열이예요 .

int main(void) {char a[] = “Hello, world”;printf(“%s\n”, a);return 0;

}

Page 29: 3.포인터

문자열의 끝은 null 문자 (\0) 으로 끝나야 합니다 .

int main(void) {char a[20];//a = “Hi”; //wrong//a[0] = “H”; //wronga[0] = ‘H’;a[1] = ‘i’;a[2] = ‘\0’;printf(“%s\n”, a);

}

Page 30: 3.포인터

문자열 관련 함수

문자열을 복사하는 함수 : strcpy()문자열을 이어주는 함수 : strcat()문자열을 개수를 세는 함수 : strlen()

다양한 함수가 있습니다 .

Page 31: 3.포인터

예제 )문자열을 복사하기 위해 필요한 공간만큼동적 할당을 하고 복사를 하는 함수를 만들어 봅시다 .int strcpy(char **src, const char *str);

Page 32: 3.포인터

#include <stdio.h>#include <stdlib.h>#include <string.h>#pragma warning(disable:4996)

void mystrcpy(char **src, const char* str) {*src = calloc(sizeof(char), strlen(str) + 1);strcpy(*src, str);

}

int main(void) {char *s;mystrcpy(&s, "Hello");printf("%s\n", s);

}

Page 33: 3.포인터

아래 두 개는 어떤 차이일까요 ?

문자열이 가변 길이이므로 위처럼 포인터의 배열의 되어야 합니다 .

아래는 에러입니다 .

char *strings[3] = { “Hello”, “world”, “Hoo” };char (*strings)[10] = { “Hello”, “world”, “Hoo”}; //error

Page 34: 3.포인터

구조체와 구조체의 포인터는 동영상 강의를 참고하세요 .

스탠포드에서 제작한 포인터와 메모리 / 링크드 리스트 문서를 읽으면 도움이 많이 됩니다 .

Page 35: 3.포인터

Thank You