[C언어 C++언어 강좌 링크 모음]
안녕하세요 양햄찌 블로그입니다.
오늘은 이차원 배열에 대해 포스팅을 다뤄보려고 합니다.
행렬을 코드로 표현하는 방법 - 2차원 배열!
코드로 2차원 행렬을 어떻게 표현할 수 있을까요?
요런 매트릭스 즉 행렬을 표현하고 싶을 수 있겠죠?
행렬끼리 더하고 빼고,, 이런 연산을 수행하고 싶을 수도 있어요.
이렇게 행과 열로 이뤄진 matrix구조를 우리는 2차원 배열로 표시할 수 있습니다.
요렇게요! 2차원 배열 또한 1차원 배열 선언 방식과 유사하죠?
2차원배열 또한 선언을 통해 틀만 잡아놓고 나중에 값을 대입할 수도 있고,
선언하면서 같이 초기화를 통해 2차원 배열을 만들어줄 수도 있습니다.
2차원 배열 선언 또는 초기화 방법
#include <iostream>
using namespace std;
int main()
{
int ary1[2][4]; //선언하기
ary1[0][0] =3; //값 대입
int ary2[2][4]{}; //0으로 초기화
cout << "ary2 출력\n";
for (int row = 0; row < 2; row++) { //-> 2차원 배열 출력방법
for (int col = 0; col < 4; col++) {
cout << ary2[row][col] << " ";
}
cout << endl;
}
int ary3[2][4] = {
{1, 2, 3, 4},
{10,20,30,40}
};
int ary4[2][4] = { 1,2,3,4,10,20,30,40 };
int ary5[2][4] = {
{1}, //나머지 3열은 0으로 초기화 {1, 0, 0, 0}과 동일
{2, 3} //니머지 2열은 0으로 초기화 {2, 3, 0, 0}과 동일
};
return 0;
}
ary1의 경우 2행 4열의 공간을 잡아준 뒤, 1행 1열에 3이라는 값을 넣어줬어요.
저번 1차원 배열에서와 마찬가지로, C언어에서 배열의 위치를 가리키는 인덱스는 1이 아닌 0부터 시작합니다.
그래서 ary1[0][0]은 가장 왼쪽위 (1,1)공간을 가리키게 되는거예요.
ary2의 경우처럼 중괄호를 사용시, 한 번에 0으로 초기화를 해줄 수 있습니다.
0으로 모두 초기화해주고 반복문을 통해서 배열의 각 원소 값을 출력으로 확인해봤습니다.
잘나오네요 :)
ary3처럼 {}를 이용해 행끼리 묶어서 초기화를 시켜줘도 되고
ary4처럼 1차원 배열처럼 일렬로 초기화를 해도 알아서 행의 개수만큼 잘라서 2차원 배열로 초기화가 됩니다.
각 요소의 값을 다 넣어주지 않았을 경우에는 ary5처럼 0으로 채워져서 초기화가 돼요.
초기값을 생략하면 나머지 원소를 0으로 초기화합니다.
메모리에서의 2차원 배열 구현
2차원 배열을 선언하고 초기화하는 방법에 대해 앞에서 살펴봤어요.
그런데 2차원 배열의 경우 어떻게 메모리에 할당될까요?
#include <iostream>
using namespace std;
int main()
{
int ary[2][4]{};
int* ptr = &ary[0][0];
cout << "메모리주소위치 \t\t offset" << endl;
for (int row = 0; row < 2 ; row++) {
for (int col = 0; col < 4; col++) {
printf("&ary[%d][%d]: %p\t", row, col, &ary[row][col]);
if(row | col)
printf("이전원소와차이 %d", (size_t)&ary[row][col] - (size_t)ptr);
ptr = &ary[row][col];
cout << endl;
}
}
}
확인을 위해 2*4 행렬을 생성한 후 각 요소들의 메모리 주소들을 출력해봤어요.
1차원 배열이 저장되듯 각 원소가 4바이트마다 차례차례 위치해있는 것을 알 수 있죠?
메모리는 물리적으로 1차원 구조이니까 어찌보면 당연한거죠.
그림으로 그리면 위와 같습니다.
즉 2차원 배열 또한 1차원 배열처럼 메모리내에서는 일렬로 할당이 된다.
2차원 행렬의 행/열 크기를 모를 때 초기화하기
int arr[] = {1,2,3,4,5};
1차원 배열에서는 출력리스트를 선언시 같이 초기화해준다면, 굳이 크기를 명시해줄 필요는 없었죠.
'[]'만 써주면 알아서 리스트 개수를 세어서 5개의 공간을 할당해줬었습니다!
int ary2d[][] = {{1,2}, {3,4}};
//이거 가능할까???
2차원 배열은 어떨까요?! 위처럼 크기를 생략해줘도 초기화가 가능할까요?
정답은 NO!!!
이차원 배열의 크기를 생략할 때는 배열의 제 1크기만 생략할 수 있습니다(행의 크기). 열의 개수는 꼭 입력을 해줘야 합니다.
왜그럴까요? 생각해보면 간단합니다.
2차원 배열이 어떻게 보면 1차원배열처럼 저장되고, 이는 곧 1차원 배열로 2차원 배열을 표현한 것과 마찬가지 인거잖아요? 그럼 "1 2 3 4 5 6"라는 일렬의 수가 있을 때, 어디까지가 첫 번째 행이고 두 번째 행이지 어떻게 알 수 있을까요?
당연히 모릅니다!
'1 2 / 3 4 / 5 6 '인 3*2 행렬일수도 있고, '1 2 3/ 4 5 6 ' 의 형태인 2*3행렬일 수도 있어요.
해석하는 컴파일러 또한 알 수 없습니다.
몇 개를 자를지 알려줘야 해요. 따라서 컬럼값이 꼭 필요한 거예요.
행의 개수를 알려주면 안되냐고요?!
행이 3개라 했을 때, '1 2 / 3 4 / 5 6 '일수도 있지만 '1 / 2 3 4 / 5 6'일수도 있겟죠?
사실 좀 더 깊이 들어가면 이는 포인터와 관련되어 있기도 한대. 뭐 이에 대한건 나중에 자세히 들여다볼꺼니까..
결론은 2차원 배열을 선언할 때에는 최소 컬럼사이즈는 지정해줘야 한다!
#include <iostream>
using namespace std;
int main()
{
//int ary1[][] = { 1,2,3,4 }; //NO
//int ary2[][] = { {1,2}, {3,4} }; //NO!
//int ary3[2][] = { 1,2,3,4 }; //NO!
//int ary4[][4]; //NO
int ary5[][4] = { 1,2,3,4 }; //YES!
int ary6[][4] = { 1,2,3,4,10,20,30,40 }; //YES!
int ary7[][4] = { 1,2,3,4,10,20 }; //YES!
int ary8[][4] = { //YES!
{1},
{2,3}
};
}
가능한 선언 및 초기화를 정리해봤어요. ㅎㅎ
2차원 배열 크기 구하고 출력하기 - sizeof
이렇게 2차원 배열 크기를 모를 경우, 어떻게 출력하지?
2차원 배열 또한 sizeof 함수로 배열크기를 확인할 수 있습니다.
#include <iostream>
using namespace std;
int main()
{
int ary[][4] = { 1,2,3,4,10,20 }; //YES!
int cols = sizeof(ary[0]) / sizeof(int);
int rows = sizeof(ary) / sizeof(ary[0]);
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
cout << ary[row][col] << " ";
}
cout << endl;
}
}
ary[0]은 1행을 의미해요. 1행의 크기를 int인 4바이트로 나눠줬으니, 총 열의 개수가 나올겁니다.
ary는 2차원 배열 전체의 크긴데, 이를 1행의 크기로 나눠줬으니 행의 개수가 나오겠죠~!
오늘은 여기까지 2차원 배열에 대해 간단하게 살펴봤습니다.
도움이 되셨다면 공감은 어떤가요?! 더 나은 정보 공유의 큰 동기가 됩니다.
오늘 하루도 고생많았어요~! 다음에 봐요~!
최신 댓글