인프런 커뮤니티 질문&답변
배열과 포인터와 포인터 산술 연산의 이해
해결된 질문
작성
·
361
5
안녕하세요, 집에서 해당 강의로 입문한 독학러 입니다.
제가 배열과 메모리, 포인터와 산술 연산을 제 기준으로 쉽게 풀어서 이해를 하였는데 이해한게 맞는건지 확인을 부탁드리고자 글을 작성하게 되었습니다.
- 포인터변수의 크기 - 포인터변수의 크기는 자료형이 무엇이든 x86(32비트)에선 4바이트, x64(64비트)에선 8바이트가 나왔습니다. 
 이러한 이유가 메모리주소에서 확인할 수가 있었는데 일단 x86(32비트)에선 왜 4바이트가 나오냐에 대한 생각인데 메모리 주소를 포인터 변수에 저장한다고 가정했을 때 메모리 주소도 값이잖아요?- 해당 값을 일단 출력해보면 아래와 같이 나옵니다.   - 이 사진으로 생각할 수 있는건 16진수의 8자리 그리고 4바이트. 즉 4바이트가 표현할 수 있는 가짓수는 2^32 = 4,294,967,296 
 0 ~ 4,294,967,295까지 여기서 4,294,967,295는 16진수로 FFFFFFFF. 위 사진의 자릿수와 같은 8자리다.
 즉 메모리 주소의 가짓수는 unsigned int과 마찬가지로 4,294,967,296만큼 가질 수 있으며 00000000 ~ FFFFFFFF 이기 때문에 x86(32비트)에선 포인터 변수는 해당 16진수의 값을 저장해야 하니 4바이트인 것이다. x64(64비트)에서도 위와 동일한 이유로 8바이트가 되는 것이다, 라고 이해했습니다. 맞게 이해했을까요??
- 배열과 포인터의 산술연산 - 배열과 포인터의 산술연산을 보고 제일 먼저 떠오른게 "주사위 게임"이였습니다. - 일단 배열을 선언하면 1차든 2차배열이든 몇겹이든 메모리 공간에 1차원적으로 차례대로 나열되어 메모리 공간이 확보되는걸 선생님 강의를 통해 이해했는데요. 이 메모리를 주사위 게임의 게임판 처럼 변형하여 생각을 해본다면 아래와 같이 될 것 같습니다.  <- 배열의 메모리공간 가정 <- 배열의 메모리공간 가정- 주사위 놀이판을 편집을 해왔습니다. - 여기서 위 그림대로 배열을 선언한다 가정했을 때 arr[3][5]가 될 것 입니다. - 1~5까진 arr[0][0] ~ arr[0][4] 
 6~10까진 arr[1][0] ~ arr[1][4]
 11~15까진 arr[2][0] ~ arr[2][4]- 자료형을 적지않은 이유는 1바이트 자료형이든 4바이트 자료형이든 저 위 그림 한칸 한칸을 하나의 인덱스라고 생각해주시면 될 것 같습니다. - 만약 int 4바이트라고 가정한다면 위 그림 1번칸엔 메모리 주소 0~3까지 있을 것이고 2번칸엔 4~7까지 있다고 생각할 수 있습니다. - 그러면 이제 저 주사위놀이판 위에 이제 말을 배치해야 인덱스칸에 접근할 수 있다고 생각해봅시다. - 그럼 그 말은 포인터변수가 될 것입니다. - *ptr = arr; 여기서 arr은 &arr[0][0] 즉 메모리의 첫주소 값을 가지고 있기 때문에 이게 몇차원 배열이든 배열변수의 이름만 적어서 포인터변수에 첫 주소를 저장합니다. - 그러면 이제 1번칸에 말이 접속하여 인덱스에 포인터변수로 접근할 수 있게 된다고 생각했습니다. - 1번칸은 [0][0] 여기서 5번칸 [0][4]으로 이동한다고 가정 한다면 4칸을 이동해야 합니다. 
 그러면 여기서 말에다가 4칸을 더하면 ptr += 4;을 하면 포인터변수의 주소는 [0][4]을 가리키고 있을 것 입니다. 여기서 바꿔 생각한다면[0][4]가 아니라 [0][i] 라고 했을 때 ptr += i; 을 더하면 [0][0] ~ [0][i] 까지 이동할 수 있을 것 입니다.- 위 방법대로 한다면 1차원이든 2차원이든 3차원이든 배열 맨 끝 [인덱스]에 포인터 변수로 접근할 수 있다고 생각합니다. 
 그러면 이제 1번칸 [0][0]에서 6번칸 [1][0]에 가고 싶다고 가정을 한다면 총 5칸을 가야 도달할 수 있습니다.
 왜냐하면 arr[3][5]으로 선언했기 때문에 뒤에 [5]인덱스가 0~4까지 총 5가짓수이기 때문입니다.- 그러면 포인터변수(말)에게 ptr+=1*5을 하면 6번칸 [1][0]에 도달할 수 있습니다. - 1번칸 [0][0]에서 11번칸 [2][0]에 갈려면 ptr += 2*5을 하면 됩니다. 즉 이걸 바꿔서 생각해본다면[0][0]에서 [j][0]로 가기 위해서는 ptr += j * 5(인덱스 총 갯수)을 이용하면 옮겨갈 수 있습니다. 
 여기서 빼기도할 수 있는데
 현재 ptr이 [0][0]에 있다고 가정하고 ptr += 2 * 5를 하면 [2][0]으로 가게 되는데 여기서 [1][0]으로 간다고 가정하면 ptr += -1 * 5를 하면 [1][0]으로 가게 된다. 위와 같은 방식으로 배열에 포인터변수로 접근하여 사용하니까 아주 쉽게 사용이 되더라구요, 반복문에서는 따로 위 그림처럼 포인터변수 = 말, 배열 = 주사위게임판 이라 생각하고 머릿속에 그리면서 하니까 원하는 값을 얻을 수 있고 이러한 방식이 괜찮은 방법 중 하나일까요? 아니면 잘못 이해하고 있는걸까요? 문장 정리능력이 없다보니 이렇게 긴 글을 적어놨는데 읽어주시면 감사하겠습니다.
답변 1
2
안녕하세요, 답변 도우미 Soobak 입니다.
- 포인터 변수의 크기에 대해서 
 : 잘 이해하고 계신 것 같습니다. 포인터 변수는 메모리 주소를 저장하기 때문에, 주소를 나타내는 데에 필요한 바이트 크기가 그대로 포인터 변수의 크기가 됩니다.- x86아키텍쳐에서는- 32비트, 즉- 4바이트로 주소를 표현하고,- x64아키텍쳐에서는- 64비트, 즉- 8바이트로 주소를 표현합니다.
- 배열과 포인터의 산술연산 
 : '주사위 게임' 이라는 비유를 통해 쉽게 이해가 되신다면 유용한 비유인 것 같습니다. 포인터 산술을 통해 계산하시는 방법도 잘 이해하고 계신 것 같습니다.- *ptr = arr;에 대해서 이해하신 부분,- ptr += 4;와- ptr[0][4]에 대해 이해하신 부분, 그리고- [0][0]인덱스에서- [j][0]인덱스로 이동하는 방법에 대한 부분 등 모두 잘 이해하고 계십니다.
대체적으로 올바르게 잘 이해하고 계신 것 같습니다. 설명을 통해 얼마나 열심히 공부하고 계신지 잘 느껴지네요.






