본문 바로가기

C 언어

2차원 배열 동적 할당하기

2차원 배열 동적 할당 

1차원 배열이 여러개 있으면 2차원 배열이다. 
4개짜리 1차원 배열이 3개가 있다고 해보자. 1차원 배열이 3개가 있으니까 2차원 배열이 된다. 


이렇듯 1차원 배열을 여러개 할당하면 2차원 배열이 되는데 1차원 배열을 할당하려고 하면 포인터가 필요하다. 왜냐하면 동적 메모리의 주소를 포인터에 저장해야하기 때문이다. 1차원 배열이 3개가 있는거니까 포인터로 3개가 필요하다. 

그런데 이렇게 포인터 변수를 각각 선언하는 순간 이름이 다 다르기 때문에 이 포인터들을 배열처럼 쓰는게 불가능해지게 된다. 그래서 2차원 배열을 동적할당하고 싶을 때 그 포인터는 모두 같은 이름을 사용해서 선언해주어야 한다. 

#include<stdio.h>
#include <stdlib.h>

int main(void) {
	int* p[3];
	int i; 

	//동적 메모리 할당
	for (i = 0; i < 3; i++) {
		p[i] = (int*)malloc(sizeof(int) * 4);
	}

}

그래서 첫번째 포인터의 이름은 p[0]
두번째 포인터의 이름은 p[1]
세번째 포인터의 이름은 p[2] 가 된다. 
이제 이름이 동일하기 때문에 배열처럼 쓸 수 있게 된다. 

 

첫 번째 배열의 포인터 p[0] 의 배열은 4개니까 
p[0] 의 첫 번째 배열은 p[0]
두번째 배열은 p[0]+1
세번쨰 배열은 p[0]+2
네번쨰 배열은 p[0]+3 이다.


이때 역참조 할 때 * 과 인덱스는 같다. 

p[0][1] == *(p[0]+1)

 


일단 역참조가 뭔지 간단히 설명해보자면, 
역참조랑 *연산자는 세가지 종류가 있다. 


1. 곱하기 : 2*a; 
2. 포인터: int* p;
3. 역참조: *p;
 
여기에서 포인터는 보통 X000X0FF 같은 메모리 공간의 주소값을 가리킨다. 
그런데 참조를 뒤집는 역참조를 하게되면 메모리 공간의 주소값이 아니라 
메모리 공간안에 있는 value 값을 가리키게 되는 것이다. 

그래서 결국 2차원 배열은 결국 어떤 자료구조로 만들어진것일까?
결국 포인터배열로 연속적인 배열을 할당해서 만든 것이라고 정의할 수 있다.
여기에서 연속적인 배열이라는 의미는 1차원 배열일때  p[0], p[0]+1, p[0]+2 와 같이 배열이 나란히 놓여져있는 상태를 의미한다. 

그렇다면 값을 하나 넣어서 2차원 배열이 진짜 만들어지는지 보도록 하자. 

#include<stdio.h>
#include <stdlib.h>

int main(void) {
	int* p[3];
	int i; 

	//동적 메모리 할당
	for (i = 0; i < 3; i++) {
		p[i] = (int*)malloc(sizeof(int) * 4);
	}
    
    for(i=0; i<3; i++){
    	for(j=0; j<4; j++){
         p[i][j] = num++; 
         printf("%4d",p[i][j]);
        }
        puts("");
    }
    return 0;
}

//출력값 
1  2  3  4
5  6  7  8
9  10 11 12