[C/C++] 2차원 배열과 메모리

🌎·2023년 11월 26일
0

오랜만에 C++을 사용하면서 코딩테스트 공부를 하다보니 2차원 배열과 포인터가 혼동이 되기 시작했다.
예전에 C공부를 할 때, 포인터 주소를 하나하나 다 찍어가보면서 어떻게든 이해하려고 노력했던 기억이 나는데도 불구하고 오랜만에 잡아보려니까 정말 하나도 모르겠더라. (1차원에선 괜찮았는데, 2차원 넘어가니까 궁금한게 너무 생기는...)

그래서 다양하게 디버그 콘솔에 찍어 보면서 내 나름대로 이해하게 된 것들을 정리하고자 한다.
(잘못된 부분은 댓글로 남겨주면 수정하도록 하겠습니다!)

내가 의문을 가졌던 코드는 아래와 같다.

#include <bits/stdc++.h>

using namespace std;

int a[10];
int b[10][10];

int main() {

    fill(&a[0], &a[10], 100);

    for(int i = 0; i < 10; i++) {
        cout << a[i] << " ";
    }

    cout << '\n';

    fill(&b[0][0], &b[0][0] + 10 * 10, 2); //여기서 의문을 갖게 되었다.
    for(int i = 0; i < 10; i++) {
        for(int j = 0; j < 10; j++) {
            cout << b[i][j] << ' ';
        }
        cout << '\n';
    }

    return 0;

}

1차원 배열로 생각하면 &a[1] 은 a + 1 과 같다.

그러면 2차원 배열로 생각하면 b[0][1]과 b[1][0]은 포인터로 어떻게 표현될까? 가 나의 의문이었다.
단순하게 나는 b[0][1] 이 b + 1 로 표현될 것이라고 착각했고, 값이 다르다는 것을 확인할 수 있었다.

왜 다를까? 나는 10 * 10 배열이더라도, 메모리에 저장되는 순서는 차례대로 이기 때문에 b + 1 이 &b[0][1]과 같을 것이라고 생각했다.
디버그 콘솔로 찍어보니 메모리에 +4를 증가시키면서 순차적으로 저장되는 것은 맞았지만, 그렇다고 해서 b + 1 이 &b[0][1] 이 지칭하는 것은 아니었다. 왜그럴까?
b[10][10] 은 아래 그림과 같이 생각하면 될 것 같다.

때문에 b + 1 은 b[0][1] 과 같은 것이 아니라 b[1][0] 와 같은 것이 맞는 답이다.

그러면 여기서 &b[0][1] 은 포인터로 어떻게 표현하는 것일까?
위 그림에서 보듯, b + 0 안에서 또 1을 증가시켜야 한다.

숫자 배열이기 때문에 포인터를 1 증가시킬 때마다 4가 증가한다.


b는 포인터를 1 증가시킬 때마다 4 * 10(배열의 크기) = 40 이 증가한다.


뒤 숫자만 비교했을 때 58 - 30 = 28(16진수)을 10진수로 바꿔보면, 40이 나오는 것을 알 수 있다.

위의 그림들은 다 이해를 쉽게 하기 위해서 그린 그림이고, 실제로 메모리엔 차례대로 저장된다.

추가적으로,
&b[0][1] 은 &b[0][0] + 1 으로
&b[1] 은 &b[0] + 1로 표현할 수 있다는 것도 알아두자.

profile
영차영차

0개의 댓글