포인터 배열이란? 2차원 배열이란? 예제로 개념이해하기
■ 포인터 배열
포인터도 변수이기 때문에 포인터를 저장하는 배열도 있습니다.
그럼 포인터 배열은 어떻게 선언해야 할까요?
일반적인 배열은 아래와 같이 선언합니다.
예) int nums[3]; // 자료형 배열명[요소 수]
int형 데이터를 넣을 수 있는 배열이지요.
그럼 포인터를 저장하는 배열은
데이터형을 포인터형으로 하면 됩니다.
예) int* num_pointers[3];
int*를 담는 배열입니다.
포인터 배열
[ 예제 코드 ]
int nums1[3] = { 11, 22, 33 };
int nums2[1] = { 90 };
int nums3[4] = { 36, 25, 45, 78 };
int* num_pointers[3];
num_pointers[0] = nums1;
num_pointers[1] = nums2;
num_pointers[2] = nums3;
[ 코드 설명 ]
배열의 이름은 그 배열의 첫 번째 요소를 가리키는 주소를 의미합니다.
그래서 num_pointers[0]에 nums1 배열 이름을 이용하여 그대로 대입할 수 있습니다.
위 예제 코드에서 순서대로
num_pointers[0]에 nums1을,
num_pointers[1]에 nums2을,
num_pointers[2]에 nums3을 대입하였습니다.
즉, num_pointers의 배열에는 각 배열의 첫 번째 요소의 주소값이 들어있습니다.
그래서 num_pointers는 포인터 배열라고 부를 수 있습니다.
■ 포인터 배열 요소 호출 방법
그럼 포인터 배열의 모든 요소를 호출하려면 어떻게 코드를 작성해야 할까요?
1차원 배열은 for문을 통해 인덱스를 1씩 증가하여 데이터에 접근하였습니다.
포인터 배열도 비슷한 개념입니다. 이중 for문을 돌 때랑 비슷하죠.
그럼 포인터 배열의 요소를 호출하는 코드를 보겠습니다.
[ 예제 코드 ]
void print_array(int* const data[]. const size_t size, const size_t length[])
{
size_t i;
size_t j;
const int* p;
for(i=0; i < size; ++i) {
p = data[i];
printf("nums[%d]:", i);
for(j=0; j<lengths[i]; ++j){
printf(" %d", p[j];
}
printf("\n";
}
}
[ 코드 설명 ]
매개변수로 포인터 배열을 넣는다는 것은 배열의 첫 번째 요소의 주소를 전달한다는 뜻입니다.
배열을 복사하지 않기 때문에 데이터를 복사하는데 시간 낭비할 필요가 없습니다.
그 외의 "포인터의 용도" 에 관해서는 아래 글을 읽어주세요.
또한 주소를 전달하기 때문에 포인터 변수만으로 배열의 길이를 알 수 없어서
함수에서 접근하려면 각 내부 배열의 길이를 알려주는 size_t 배열이 필요합니다.
자 여기까지 이해하셔야 다음 2차원 배열을 받아들일 준비가 된 것입니다.
- 배열의 이름은 배열의 첫 번째 요소의 주소를 의미한다.
- 포인터 배열과 배열 포인터는 다르다.
- 포인터 배열 선언 방법 이해했다.
위 3가지에 완전히 동의하신다면 2차원 배열로 넘어가보겠습니다.
■ 2차원 배열
2차원 배열 선언은 아래와 같이 합니다.
int matrix[3][5] = { // 자료형 배열이름[행 갯수][열 갯수]
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 }
};
그럼 포인터 개념을 이용하여 호출할 때 이렇게 코드를 작성하면 될까요?
void do_magic(int* matrix[5])
{
/* 코드 생략 */
{
int main(void)
{
int matrix[3][5] = { // 자료형 배열이름[행 갯수][열 갯수]
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 }
};
do_magic(matrix);
}
위 코드를 실행하면 컴파일 오류가 발생합니다.
2차원 배열은 한 덩어리 메모리라 주소값이 저장된 곳이 없기 때문입니다.
그래서 다음과 같이 작성해야 합니다.
void do_magic(int matrix[][5], size_t m) //m은 행의 수, 각 행마다 5개 데이터 있음
{
/* 코드 생략 */
}
matrix[몇 번째 줄],[데이터 5개있다] 라는 뜻이라
matrix[1],[] 하면 컴파일러가 '두번째 줄을 호출하려면 몇 바이트를 뛰어넘어야겠구나.'하고 알 수 있습니다.
위 코드대로 라면 matrix[1],[] 는 배열 시작 주소보다 20바이트(4바이트 * 요소 5개) 뒤를 호출하겠네요.
컴파일할 수 있는 수정된 코드 전체를 보겠습니다.
행의 수는 모르기 때문에 전달해주어야 합니다.
void do_magic(int matrix[][5], size_t m)
{
/* 코드 생략 */
{
int main(void)
{
int matrix[3][5] = { // 자료형 배열이름[행 갯수][열 갯수]
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 },
{ 1, 2, 3, 4, 5 }
};
do_magic(matrix, 3);
}
-----------------------------------
-----------------------------------
'컴퓨터 공학 > C, C++' 카테고리의 다른 글
[ C ] 포인터 이해하기11_포인터 개념 정리 / 용도 / 복습 또 복습하기 (404) | 2020.07.21 |
---|---|
[ C ] 포인터 이해하기10_다중, 이중 포인터란? / 다중 포인터 사용하는 이유 (399) | 2020.07.21 |
[ C ] 포인터 이해하기8_함수 포인터 쉽게 읽는 방법 (1573) | 2020.07.20 |
[ C ] 포인터 이해하기7_함수 포인터란? 함수를 포인터에 저장할 수 있을까? (987) | 2020.07.20 |
[ C ] 포인터 이해하기6_void 포인터 개념 / 활용도 (411) | 2020.07.19 |
댓글