포인터와 배열, 포인터 연산

배열의 이름은 포인터이고, 값을 바꿀 수 없는 상수 형태의 포인터입니다. 또한, 배열의 요소들은 연속적인 메모리 주소값을 가지게 됩니다.

1. 1차원 배열

int arr[5] = {9, 2, 10, 3, 0};

printf("arr = %p\n", arr);
printf("arr+1 = %p\n", arr+1);
printf("arr+2 = %p\n", arr+2);
printf("arr[0]의 주소 = %p\n", &arr[0]);
printf("arr[1]의 주소 = %p\n", &arr[1]);
printf("arr[2]의 주소 = %p\n", &arr[2]);
printf("arr[3]의 주소 = %p\n", &arr[3]);
printf("arr[4]의 주소 = %p\n", &arr[4]);

결과

arr = 0x7ffccff3c200
arr+1 = 0x7ffccff3c204
arr+2 = 0x7ffccff3c208
arr[0]의 주소 = 0x7ffccff3c200
arr[1]의 주소 = 0x7ffccff3c204
arr[2]의 주소 = 0x7ffccff3c208
arr[3]의 주소 = 0x7ffccff3c20c
arr[4]의 주소 = 0x7ffccff3c210

0x00 -> 0x04 -> 0x08 -> 0x0c(c=12) -> 0x10(=16이 되었으므로 앞자리로 넘어감)

int형 변수의 크기만큼 메모리 주소가 연속적이라는 것을 알 수 있고, arr과 arr[0]의 주소값이 같으므로 arr = &arr[0], 배열의 이름이 포인터가 되는 것입니다.

그럼 arr+1은 어떻게 될까요? arr+1 = &arr[1]이 됩니다. 포인터의 값을 1 증가시키면 실제 메모리 주소는 4(int배열이므로 int의 크기만큼)가 증가합니다. 그럼 arr+2 = &arr[2]을, arr+3 = &arr[3]...을 의미하게 됩니다.

 

2. 2차원 배열

그럼 2차원 배열의 포인터는 어떻게 될까요?

1차원 배열에서는 a[0]가 값이지만 2차원 배열에서 a[0]는 a[0][0]을 가리키는 포인터가 됩니다. a[1]도 마찬가지로 a[1][0]을 가리키는 포인터가 되고, a[0][1]을 주소로 표현하면 *(a+0)+1이 됩니다.

*(a)라는 a가 가진 주소값(a[0][0]의 주소값)에 1을 더해 변수크기만큼 메모리 주소값을 증가시켜 다음 인덱스의 주소값을 표현할 수 있게 되는 방식입니다.

*(a+1)은 a+1, 즉 a[1][0]의 주소값에서 *(a+1)+n으로 1씩 증가시키면 a[1][1], a[1][2],,의 주소를 표현할 수 있게 됩니다.

그러나, a와 a[0]가 같은 것을 의미할까요? 답은 아니다 입니다.

a[3][4]의 배열에서 a와 a[0]를 출력해보면 같은 주소를 가리키고 있지만, a의 크기는 48byte가 나오고, a[0]의 크기는 16byte가 나옵니다. 이것이 의미하는 바는 a는 첫번째 요소를 가리키면서 배열 전체를 의미하는 포인터이고, arr[0]는 첫번째 요소를 가리키되 1행만을 의미하는 포인터라는 것을 알 수 있습니다.

 

<연결 리스트와 배열의 차이점>
배열은 메모리 주소들이 연속적이고 연결 리스트는 불연속적인 메모리 주소들이 연결된다는 차이가 있습니다.

출처 : https://medium.com/@jillplatts/6-minute-beginners-guide-to-java-s-linked-list-data-structure-bb2fbcca81b1

 

'Study' 카테고리의 다른 글

포인터 C++  (0) 2021.12.02
1. make, cmake  (0) 2021.12.02