13. 포인터와 배열! 함께 이해하기
I. 포인터와 배열의 관계
-
배열의 이름은 무엇을 의미하는가?
- 배열의 이름은 포인터다. 단 그 값을 바꿀수 없는 상수라는 점이 일반적인 포인터와의 유일한 차이점
- #include <iostream>
- using namespace std;
- 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는 같다.
비교대상 | 포인터 | 배열이름 |
비교조건 | ||
이름이 존재하는가 | 물론 있다. | 당연히 있다. |
무엇을 나타내는가 | 메모리의 주소 | 메모리의 주소 |
변수인가 상수인가 | 변수 | 상수 |
- 포인터와 배열이름의 차이점은 배열이름이 상수이다보니 상관 없다. 따라서 상수 포인터라 한다.
- int main()
{
int a[5] = {0,1,2,3,4};
int b = 10;
a = &b;
}
- 마지막 줄 a는 상수 이므로 변수인 &b를 넣을수 없다.
-
1차원 배열이름의 포인터 타입
- int a[10] 이라면 int*형이다.
- 포인터를 배열의 이름처럼 사용할 수 있다.
- #include <iostream>
using namespace std;
int main()
{
int arr[3] = {0,1,2};
int *ptr; - ptr = arr;
- printf("%d,%d,%d\n",ptr[0],ptr[1],ptr[2]);
return 0;
}
- 위 소스처럼 arr를 포인터 처럼 써서 넘겨줄 수 있다.
II. 포인터 연산
- 포인터는 제한된 형태의 연산이 가능하다
- #include <iostream>
using namespace std;
int main()
{
int *ptr = 0;
char *ptr1 = 0;
double *ptr2 = 0; - printf("%d,%d,%d\n",ptr++,ptr1++,ptr2++);
printf("%d,%d,%d\n",ptr,ptr1,ptr2);
return 0;
}
-
먼저 ptr,ptr1,ptr2를 찍고 각각 하나씩 증가한다음 각 타입만큼 증가 시켜서 그다음번에 4,1,8을 찍는다.
- 포인터 연산에 따른 실질적인 값의 변화는 포인터 타입에 따라 다르다.
- #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)); - return 0;
}
-
위의 소스를 보면 *(parr+1) 같은것이 보인다.
- 잘 생각해보면 parr은 배열의 이름(즉 배열의 첫번째 주소값)이 들어가있다. 거기에 +n 을 하면 더한만큼의 배열을 가리킨다.
-
중요한 결론! arr[i] = *(arr+i)
III. 문자열 상수를 가리키는 포인터
-
문자열 표현 방식의 이해
-
- 변수로 표현하는 방법 : char str1[5] = "ABCD";
- 상수로 표현하는 방법 : char *str2 = "abcd;
- #include <iostream>
using namespace std;
int main()
{
char str1[5] = "abcd";
char *str2 = "ABCD"; - printf("%s\n",str1);
printf("%s\n",str2); - str1[0] = 'x';
str2[0] = 'x';
printf("%s\n",str1);
printf("%s\n",str2);
return 0;
}
-
위의 소스는 컴파일은 잘된다 하지만 실행시 오류가 난다 어디서 날까?
- str2[0] = 'x'; 이것이 잘못 된 것이다. 왜냐하면 str2는 문자열 상수를 변경하려고 하기 때문이다.
-
문자열 상수에 대한 조금 더 깊은 이해
- 문자열 상수는 메모리 공간에 할당되면 주소를 반환한다.
- 똑같은 문자열을 선언하면 한번만 메모리 공간에 할당된다.
- #include <iostream>
using namespace std;
int main()
{
char *str1 = "ABCD";
char *str2 = "ABCD";
printf("%d,%d\n",str1,str2);
return 0;
}
- 좋은 컴파일러는 똑같은 코드라 할지라도 메모리를 효율적으로 사용하기위해서 최적화를 한다.
IV. 배열 요소로 포인터를 지니는 포인터 배열
- 포인터 배열의 이해
- #include <iostream>
using namespace std;
int main()
{
int a = 10, b= 20, c = 30;
int* arr[3]={&a,&b,&c}; - printf("%d\n",*arr[0]);
printf("%d\n",*arr[1]);
printf("%d\n",*arr[2]);
return 0;
}
- 그림으로 설명하겠다.
문제
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 |