Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

3.포인터

  • Be the first to comment

3.포인터

  1. 1. C언어와 포인터 (3) 포인터 학습 "완전학습을 지향하는" NHN NEXT 정호영 나눔고딕 및 나눔고딕코딩 글꼴을 설치해 주세요.
  2. 2. 오늘의 토픽 1. 함수에 배열을 건네주기 2. 2차원 배열과 포인터 3. 문자열과 포인터 4. 구조체와 포인터
  3. 3. 0. TIP
  4. 4. 짧은 팁: (*&) 또는 (&*) 는 상쇄되어 사라집니다. int main(void) { int a = 4; int *p = &a; printf("%d %dn", *&a, a); printf("%p %pn", &*p, p); }
  5. 5. 이중 포인터 다시 보기 int x = 10; int *ptr = &x; int **pptr = &ptr;
  6. 6. 이중 포인터 다시 보기 / - *는 연속해서 올 수 있지만 &는 안 됩니다. - 이것보다는 그림이 더 명확합니다. int x = 10; int *ptr = &x; int **pptr = &ptr; /* 1) pptr = &ptr, ptr = &x 2) pptr = &ptr = &&x (아님) 2) *pptr = *(&ptr) = ptr 3) **pptr = **(&ptr) = *ptr = *(&x) = x = 10 */
  7. 7. 배열과 포인터의 차이점 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
  8. 8. 1. 함수에 배열을 건네주기
  9. 9. 예제) 크기가 n인 int 배열에 0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오.
  10. 10. 예제) 크기가 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(“%dn”, arr[i]); return 0; }
  11. 11. 배열과 포인터는 다릅니다. int *a; 와 int a[]; 는 서로 다른 문장인데 딱 한 경우에는 완전히 같습니다. 언제?
  12. 12. int *a; 와 int a[]; 는 서로 다른 문장이지만 parameter 안에서는 같습니다. void foo(int *a) = void foo(int a[]) = void foo(int a[10]) 마지막 줄의 숫자는 아무 의미가 없습니다. 무시됩니다.
  13. 13. 1차원 배열은 배열이 아니라 포인터로 넘겨주기 때문에 1) 자동으로 Call by Reference가 된다. 2) 배열의 크기를 알 수 없다. 2의 이유로 C언어에서는 배열의 크기를 반드시 따로 전달해야 합니다.
  14. 14. 예제) 크기가 n인 배열에 0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오.
  15. 15. 예제) 크기가 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(“%dn”, arr[i]); return 0; }
  16. 16. 예제) 크기가 n인 배열을 동적 할당으로 생성하고 0 ~ n – 1 까지 값을 초기화하는 함수를 작성하고 테스트하시오.
  17. 17. 예제) 크기가 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(“%dn”, (*ptr)[i]); return 0; }
  18. 18. 2. 2차원 배열과 포인터
  19. 19. 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("%pn", &arr[i][j]); }
  20. 20. arr[m][n] 배열을 1차원 포인터로 캐스팅하면 arr[m][n]; //m * n 배열 int *ptr = (int *) arr; 라면… arr[i][j] = *(ptr + i * n + j)
  21. 21. 예제) 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"); } }
  22. 22. 앞의 예제에서 알 수 있는 것처럼 이차원 배열과 단일 포인터는 서로 다른 타입입니다. 그럼 이차원 배열의 이름은 어떤 타입의 주소일까요? int 조금 복잡하지만 -ptr 변수는 int 3개짜리 배열의 포인터입니다. -이차원 배열은 1차원 배열의 배열이다. int arr[2][3] = { { 0, 1, 2 }, { 3, 4, 5 } }; int (*ptr)[3] = arr; //ok
  23. 23. 예제) 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"); } }
  24. 24. arr[i][j] = (*(arr+ i))[j] = *(*(arr +i) + j) 원리는 이런데 쓸모는 없습니다.
  25. 25. 함수로 이차원 배열을 전달하려면 1. 단일 포인터로 캐스팅해서 전달 또는 2. 배열의 포인터로 전달 두 가지 방법이 있습니다.
  26. 26. 예제) 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); }
  27. 27. 3. 문자열과 포인터
  28. 28. 문자열은 그냥 문자의 1차원 배열이예요. int main(void) { char a[] = “Hello, world”; printf(“%sn”, a); return 0; }
  29. 29. 문자열의 끝은 null 문자(0) 으로 끝나야 합니다. int main(void) { char a[20]; //a = “Hi”; //wrong //a[0] = “H”; //wrong a[0] = ‘H’; a[1] = ‘i’; a[2] = ‘0’; printf(“%sn”, a); }
  30. 30. 문자열 관련 함수 문자열을 복사하는 함수: strcpy() 문자열을 이어주는 함수: strcat() 문자열을 개수를 세는 함수: strlen() 다양한 함수가 있습니다.
  31. 31. 예제) 문자열을 복사하기 위해 필요한 공간만큼 동적 할당을 하고 복사를 하는 함수를 만들어 봅시다. int strcpy(char **src, const char *str);
  32. 32. #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("%sn", s); }
  33. 33. 아래 두 개는 어떤 차이일까요? 문자열이 가변 길이이므로 위처럼 포인터의 배열의 되어 야 합니다. 아래는 에러입니다. char *strings[3] = { “Hello”, “world”, “Hoo” }; char (*strings)[10] = { “Hello”, “world”, “Hoo”}; //error
  34. 34. 구조체와 구조체의 포인터는 동영상 강의를 참고하세요. 스탠포드에서 제작한 포인터와 메모리 / 링크드 리스트 문 서를 읽으면 도움이 많이 됩니다.
  35. 35. Thank You

    Be the first to comment

    Login to see the comments

  • happyhooni

    Dec. 17, 2014

Views

Total views

1,159

On Slideshare

0

From embeds

0

Number of embeds

263

Actions

Downloads

19

Shares

0

Comments

0

Likes

1

×