작성
·
195
1
int main()
{
int arr[5] = { 1,2,3,4,5 };
int* ptr1, * ptr2, * ptr3;
ptr1 = arr;
ptr3 = ptr1 + 4;
printf("%p, %d %p\n", ptr3, *ptr3, &ptr3);
return 0;
}
위 코드에서 ptr3 = ptr1 + 4 라는 점이 제가 이해하기로는
ptr3이 ptr1의 첫번째 주소에서 (int 크기만큼) 4칸 이동한 주소이다 라고 이해했습니다
그래서 ptr3[0]이나 *ptr3을 출력해보았을때 5가 나오고
ptr3[1]이나 ptr3[2] 등을 출력해보면 쓰레기값이 나왔습니다
여기서 궁금한점이 ptr1은 배열의 형식을 갖고있는데
ptr3도 배열의 형식을 갖고있는지가 궁금합니다
단순히 ptr1 + 4의 주소만 받은건지 아니면 배열의 형식도 같이 받은건지 궁금합니다
답변 2
4
안녕하세요.
사실 배열인 arr이나 포인터인 ptr1, ptr3이나 모두 어떤 배열의 형식을 가지고 있는게 아닙니다. 배열이름인 arr 에조차도 오로지 주소만 저장이 되어 있어요! 그리고 사실 arr도 주소값을 변경할 수 없는 상수 '포인터'나 마찬가지입니다.
arr, ptr1, ptr3 모두 다 주소값을 저장하는 포인터 '변수'일 뿐입니다.
배열이름 뿐만 아니라 모든 포인터는 [] 연산자를 사용할 수 있습니다.(int, double같은 기본 자료형의 포인터 한정) ptr[3] 연산은 곧 *(ptr + 3)이나 마찬가지입니다. 즉 ptr이 가지고 있는 주소에서 3 칸 더 떨어진 주소에 있는 데이터를 의미하는 것이나 마찬가지입니다. 사실 배열 이름도 포인터이니 당연하겠죠!
arr도 데이터 1이 있는 곳의 주소를 가지고 있을 뿐이고, ptr1도 arr의 주소 즉 데이터 1이 있는 곳의 주소를 가지고 있을 뿐이고, ptr3은 ptr1 + 4 즉 ptr1이 가리키는 곳에서 4 칸 떨어져있는 곳의 주소를 가질 뿐입니다.
- arr은 첫번째 원소인 1 의 주소를 담고 있습니다.(arr + 0) 그뿐입니다. arr은 1 데이터가 있는 메모리의 주소를 가지고 있는 상수 포인터일 뿐입니다. '배열'이라는 자료구조는 모든 원소들이 메모리상에서 바로 이웃사이로 따닥따닥 다 붙어서 자리잡습니다. 그래서 arr[0] ~ arr[4] 으로 1,2,3,4,5 데이터들에 바로바로 접근할 수 있게 됩니다. 다 이웃 사이로 붙어서 자리잡고 있기 때문입니다. arr[5]부터는 배열의 범위를 벗어난 곳에 접근하는 것이니 쓰레기값이 나오겠지만요! arr[3]은 arr + 3 주소에 있는 데이터와 동일합니다.
- ptr은 arr[3]의 주소를 대입받았습니다. 즉 ptr은 arr + 3 주소에 있는 데이터인 4 가 있는 메모리의 주소를 받았습니다. ptr은 4 데이터가 있는 공간의 주소를 담고 있을 뿐이니다.
- 그러니 ptr[1]은 즉, ptr은 현재 데이터인 4 가 있는 메모리의 주소를 담고 있으니 여기서 더 한칸 가면 데이터 5 가 있는 메모리의 주소겠지요. 그래서 ptr[1]은 데이터 5 가 있는 메모리 주소를 의미하게 됩니다. ptr + 1 이 된 것이나 마찬가지이기 떄문입니다. ptr[1]은 ptr + 1 주소에 있는 데이터와 동일합니다.
- ptr[3]은 ptr + 3 주소에 있는 데이터를 가져오는 것이나 마찬가지이므로 데이터인 4 가 있는 메모리의 주소에서 3 칸 더 떨어진 곳을 가리킵니다. 이는 arr배열의 범위를 벗어난 메모리 공간을 접근하는 것이므로 쓰레기값이 나온 것을 볼 수 있습니다.
0