작성
·
383
0
포인터 변수 ptr이 어떤 원리로 *(ptr + 3 + COLS * 2)에 접근하는지 모르겠습니다.
printf("%d\n", data[2][3]);
int* ptr = &data[0][0];
printf("%d\n", *(ptr + 3 + COLS * 2));
위의 data[2][3]을 포인터 연산을 통해 접근한다.
*(ptr + 3 + COLS * 2)에서 Row 숫자가 2로 들어가고, 그 다음 COLUMN의 개수를 곱하고
Column의 인덱스를 더하고 포인터변수 ptr로 접근하면 마치 1차원 배열로 2차원 배열에 접근할 수 있다.
라고 하셨었는데,
*(ptr + 3 + COLS * 2)는
내부적으로 COLS * 2가 먼저 계산되어 *(ptr + 3 + 8)이 되고,
그 다음 *(ptr + 11)이 되어서 결과적로 data[0][11]에 접근하게 되는게 아닌가 싶습니다.
*(ptr + 3 + COLS * 2)가 최종적으로 data[2][3]으로 접근하게되는 과정을 설명해주시면 감사하겠습니다.
답변 1
0
포인터를 사용한 접근은 데이터의 메모리 주소를 이용한 접근과 동일합니다.
배열은 1차원이든 2차원이든 저장된 값을 순차적으로 주소에 적재하게 됩니다.
일상생활에서 예를 든다면
초, 중, 고 학교에서 한 반에 출석 순서대로 앉았을 때
1 2 3 4
5 6 7 8
9 10 11 12
5번 학생이 자기 자리를 말할 때 첫째 줄의 두번째 자리야 라고 말하는 것은 배열을 이용한 접근
자신이 반에서 몇번인지 말할 때 5번째야 라고 말하는 것은 포인터를 이용한 접근 이라고 생각할 수 있을 것 같습니다.
순차적으로 메모리에 적재된 데이터를 사람이 구별하기 쉽게 구분해 놓은 것 이라고 말할 수도 있겠네요.
각설하고 적어주신 코드를 이용해 설명해 보겠습니다
data[ROWS][COLS] (ROWS = 3, COLS = 4) 라고 할때 값은 1 ~ 12 이고
주소의 시작을 0번이라고 가정 하겠습니다.
0번 주소 = 1
1번 주소 = 2
2번 주소 = 3
3번 주소 = 4
....
11번 주소 = 12
12번째 값을 얻기 위해서는 배열은 data[2][3]의 형식으로 값을 얻어오겠지만,
포인터를 사용하면 다릅니다.
int* ptr = &data[0][0];
해당 구문을 사용해 data 배열의 첫 주소를 포인터 변수에 대입해 주었습니다.
현재 포인터 변수가 가리키는 값은 0번 주소의 값 즉, 1입니다.
포인터 변수가 가리키는 주소에 사칙연산을 사용 한다면 그만큼 다음 주소의 값을 가리키게 됩니다.
(ptr + 1)
해당 포인터가 가리키는 주소는 1번 주소입니다. 값은 2가 되겠네요.
(값을 얻고 싶다면 앞에 포인터를 추가해주어야 합니다) ex) *(ptr + 1)
제가 설명을 잘하는 편이 아니라 이해되지 않는 부분이 있다면 말씀해주시기 바랍니다.
헉 2차원 배열은 내부적으로 1차원적으로 나열되어있다는 사실을 간과했네요!
그리고 인덱스가 0부터 시작한다는 것도 무의식적으로 고려하지 않았습니다.
다시한번 차분히 생각해보니 이해할 수 있었습니다.
일반적으로 곱셈하는 것처럼 가로로 10개 묶음씩 있는 뭉텅이라고 했을 때
53 = 3 + 10 x 5 라고 하는 것과 비슷한 맥락으로
*(&배열[0][0] + (column의 index) + (전체 Column 개수) * (row의 index))
라고 할 수 있었네요.
처음엔 단순히 '1차원 배열일 때 포인터 연산을 통한 간접접근'을 생각하다보니, 처음 갖고온 주소가 배열의 첫 주소, 그러니까 &arr[0][0]이 될 것이고, 여기서 11을 더하니까 &arr[0][11]가 되겠다, 싶었는데
이건 2차원 배열인 경우이므로 다릅니다.
그리고 인덱스가 0부터 시작한다는 것도 고려하지 않다보니,
처음엔 arrr[2][3]의 원소가 2행 3열, 7이 된다고 생각했습니다. 그러다보니 *(ptr + 11)의 결과가 7이 아닌데 왜 이럴까? 했던 것 같아요.
친절히 답변해주셔서 정말 감사합니다.