13. 포인터와 배열! 함께 이해하기

I. 포인터와 배열의 관계

  • 배열의 이름은 무엇을 의미하는가?

    • 배열의 이름은 포인터다. 단 그 값을 바꿀수 없는 상수라는 점이 일반적인 포인터와의 유일한 차이점
  1. #include <iostream>
  2. using namespace std;
  3. int main()
    {
     int a[5] = {0,1,2,3,4};
     printf("%d, %d\n",a[0],a[1]);
     printf("%d, %d\n",&a[0],&a[1]);
     printf("배열이름 : %d\n",a);
     return 0;
    }
  • 위의 소스를 보면 처음의 printf는 a[0],a[1]의 값을 찍는거고 , 두번째 printf는 각각의 주소값을 세번째 printf는 배열이름에 대한 주소를 찍는다.

    • 결과를 보면 &a[0]와 a는 같다.
비교대상 포인터 배열이름
 비교조건  
 이름이 존재하는가 물론 있다.  당연히 있다.
 무엇을 나타내는가  메모리의 주소  메모리의 주소
 변수인가 상수인가  변수 상수
  • 포인터와 배열이름의 차이점은 배열이름이 상수이다보니 상관 없다. 따라서 상수 포인터라 한다.
  1. int main()
    {
     int a[5] = {0,1,2,3,4};
     int b = 10;
     a = &b;
    }
  •  마지막 줄 a는 상수 이므로 변수인 &b를 넣을수 없다.

 

  •  1차원 배열이름의 포인터 타입

    • int a[10] 이라면 int*형이다.
  • 포인터를 배열의 이름처럼 사용할 수 있다.
  1. #include <iostream>
    using namespace std;
    int main()
    {
     int arr[3] = {0,1,2};
     int *ptr;
  2.  ptr = arr;
  3.  printf("%d,%d,%d\n",ptr[0],ptr[1],ptr[2]);
     return 0;
    }
  •   위 소스처럼 arr를 포인터 처럼 써서 넘겨줄 수 있다.

II. 포인터 연산

  • 포인터는 제한된 형태의 연산이 가능하다
  1. #include <iostream>
    using namespace std;
    int main()
    {
     int *ptr = 0;
     char *ptr1 = 0;
     double *ptr2 = 0;
  2.  printf("%d,%d,%d\n",ptr++,ptr1++,ptr2++);
     printf("%d,%d,%d\n",ptr,ptr1,ptr2);
     return 0;
    }
  • 먼저 ptr,ptr1,ptr2를 찍고 각각 하나씩 증가한다음  각 타입만큼 증가 시켜서 그다음번에 4,1,8을 찍는다.

    • 포인터 연산에 따른 실질적인 값의 변화는 포인터 타입에 따라 다르다.
  1. #include <iostream>
    using namespace std;
    int main()
    {
     int arr[5] = {1,2,3,4,5};
     int *parr = arr;
     printf("%d\n",*parr);
     printf("%d\n",*(++parr));
     printf("%d\n",*(++parr));
     printf("%d\n",*(parr+1));
     printf("%d\n",*(parr+2));
  2.  return 0;
    }
  • 위의 소스를 보면 *(parr+1) 같은것이 보인다.

    • 잘 생각해보면 parr은 배열의 이름(즉 배열의 첫번째 주소값)이 들어가있다. 거기에 +n 을 하면 더한만큼의 배열을 가리킨다.
  •  중요한 결론! arr[i] = *(arr+i)

III. 문자열 상수를 가리키는 포인터

  • 문자열 표현 방식의 이해

    •  변수로 표현하는 방법 : char str1[5] = "ABCD";
    • 상수로 표현하는 방법 : char *str2 = "abcd;
  1. #include <iostream>
    using namespace std;
    int main()
    {
     char str1[5] = "abcd";
     char *str2 = "ABCD";
  2.  printf("%s\n",str1);
     printf("%s\n",str2);
  3.  str1[0] = 'x';
     str2[0] = 'x';
     printf("%s\n",str1);
     printf("%s\n",str2);
     return 0;
    }
  •  위의 소스는 컴파일은 잘된다 하지만 실행시 오류가 난다 어디서 날까?

    •  str2[0] = 'x'; 이것이 잘못 된 것이다. 왜냐하면 str2는 문자열 상수를 변경하려고 하기 때문이다.
  • 문자열 상수에 대한 조금 더 깊은 이해

    • 문자열 상수는 메모리 공간에 할당되면 주소를 반환한다.

1.jpg 

  • 똑같은 문자열을 선언하면 한번만 메모리 공간에 할당된다.
  1. #include <iostream>
    using namespace std;
    int main()
    {
     char *str1 = "ABCD";
     char *str2 = "ABCD";
      printf("%d,%d\n",str1,str2);
     return 0;
    }
  • 좋은 컴파일러는 똑같은 코드라 할지라도 메모리를 효율적으로 사용하기위해서 최적화를 한다.

IV. 배열 요소로 포인터를 지니는 포인터 배열

  • 포인터 배열의 이해
  1. #include <iostream>
    using namespace std;
    int main()
    {
     int a = 10, b= 20, c = 30;
     int* arr[3]={&a,&b,&c};
  2.  printf("%d\n",*arr[0]);
     printf("%d\n",*arr[1]);
     printf("%d\n",*arr[2]);
     
     return 0;
    }
  • 그림으로 설명하겠다.

 2.jpg

 

문제

13-1

문제 1

크기 5인 int형 배열 arr을 선언하고 1,2,3,4,5로 초기화 한다음 포인터 p를 선언해서 배열 arr의 첫 번재 요소를 가리키게 한다. 그 다음 포인터 p를 조작해서 배열 요소의 값을 2씩 증가시킨후, 전체 배열 요소를 출력

 

문제 2

 1번 문제와 유사하다. 크기 5인 int형 배열 arr을 선언하고 1,2,3,4,5로 초기화 한다음 포인터 p를 선언해서 배열 arr의 첫 번재 요소를 가리키게 한다. 그 다음에는 포인터p를 이용해서 배열 요소의 순서를 뒤바꾼 후, 그 결과를 출력하는 프로그램 작성

 

이 글은 스프링노트에서 작성되었습니다.

'2. C/C++ > 01. C' 카테고리의 다른 글

17. 포인터의 포인터  (0) 2008.12.07
16. 다차원 배열  (0) 2008.12.07
14. 포인터와 함수에 대한 이해  (0) 2008.12.07
12. 포인터의 이해  (0) 2008.12.07
11. 1차원 배열  (0) 2008.12.07
Posted by kid1412
,