2차원 배열과 포인터
1. 2차원 배열
A. 배열의 배열
Int array[5][10];
Int형 변수 10개를 묶어 배열을 만들고, 이러한 배열 5개를 묶어 다시 배열을 만들겠다는 뜻입니다. 총 50개의 int형 변수가 메모리의 연속된 공간에 만들어집니다. Array[0][0] 부터 뒤쪽 인덱스가 먼저 증가 하며 array[4][9] 까지 만들어 집니다. 즉, 가로 축 10개, 세로 축 5개의 원소가 있다고 생각할 수 있는 것입니다.
B. 2차원 배열의 초기화
int array[2][3] = {{1,2,3}, {4,5,6}};
int array[2][3] = {1,2,3,4,5,6};
//안쪽중괄호생략가능
int array[2][3] = {{1}, {4,5}};
//지정되지않은값은0으로초기화됨
int array[][3] = {1,2,3,4,5,6};
//빈브래킷안에들어갈숫자가2라는것을컴파일러가판단
int array[2][] = {1,2,3,4,5,6};
//마지막브래킷의수는컴파일러가자동으로판단불가->error발생!!
C. 2차원 배열의 활용
#include <stdio.h>
#define LESSONS 3
int main(void)
{
int students; //학생수
int sum = 0; //합계
int l, s; //for루프를위한임시변수
int score[][LESSONS] =
{
{85,02,95},//1번째학생의점수
{70,82,60},//2번째학생의점수
{92,88,88},//3번째학생의점수
{94,75,79},//4번째학생의점수
{95,68,78},//5번째학생의점수
{82,79,88},//6번째학생의점수
{68,80,95},//7번째학생의점수
{78,84,92}//8번째학생의점수
};
students = sizeof(score)/sizeof(score[0]); //학생수계산
for(l=0;l<LESSONS;l++) //과목 수만큼 루프
{
sum = 0;
for(s=0;s<students;s++) //학생 수만큼 루프
{
sum += score[s][l]; //과목별 총합 계산
}
printf("[%d] Total : %d, ", l, sum);
printf("Average : %0.2f\n", (double)sum/students);
}
getchar();
}
<v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f><o:lock aspectratio="t" v:ext="edit"></o:lock>
1차원 배열에서와는 달리, 3과목의 성적을 일괄 처리하도록 하는 것입니다. 8명의 학생에 대해 각각 3과목씩 점수가 나올 테니까 8*3, 총 24개의 점수를 처리해야 합니다. 과목별로 총점과 평균을 따로 계산해야 하기 때문에 8*3의 크기를 갖는 2차원 배열을 사용하는 것이 좋습니다.
2. 가변 크기 2차원 데이터
차원을 확장 했어도 배열을 이용하면 고정된 개수의 데이터만 처리할 수 있습니다. 따라서 처리할 데이터의 개수를 가변적으로 하려면 배열 대신 포인터를 쓰면 됩니다. 그런데 2차원 데이터는 가로축과 세로축에 대해 각각 크기가 고정인 경우와 가변인 경우가 있을 수 있으므로 총 4가지 방법으로 배열과 포인터를 조합할 수 있습니다. 즉, 가로, 세로축으로 데이터의 개수가 고정적인지, 가변적인지에 따라 배열을 쓸지 포인터를 쓸지가 결정되어 2차원배열(배열의 배열), 포인터의 배열, 배열의 포인터, 2차원 포인터(포인터의 포인터) 등 4가지 방법으로 2차원 데이터를 다룰 수 있습니다.
| 가로축 | ||
고정 개수 | 가변 개수 | ||
세로축 | 고정 개수 | 2차원 배열(배열의배열) | 포인터의 배열 |
가변 개수 | 배열의 포인터 | 2차원 포인터(포인터의 포인터) |
A. 포인터의 배열 – 포인터 여러 개를 엮어서 배열로 만든 것입니다.
Char *ptrArray[5];
위와 같이 하면 char형 포인터 5개로 이루어지는 배열이 선언됩니다. 포인터의 배열은 배열의 각 원소가 포인터로 이루어져 있어서, 이를 이용해 다른 곳에 저장된 데이터를 가리킬 수 있습니다.
좌측 부분이 바로 포인터의 배열입니다. 포인터의 배열은 일종의 배열이기 때문에 그 자체는 고정된 개수를 갖지만, 포인터가 가리키는 데이터는 크기가 가변적일 수 있기 때문에 가로축으로는 가변 개수, 세로축으로는 고정 개수인 2차원 데이터를 다룰 수 있습니다.
포인터는 데이터가 저장된 위치를 가리키기만 할 뿐, 데이터를 저장할 공간을 할당해 주지는 않기 때문에 실제 데이터가 저장되는 공간은 malloc 등의 함수를 호출하여 별도로 할당 해야 하는데, 포인터의 배열을 사용할 때도 이점은 마찬가지입니다.
B. 배열의 포인터 – 배열을 가리키는 포인터
Char (*arrayPtr)[10];
위와 같이 하면 char 형 데이터 10개로 이루어지는 배열을 가리키는 포인터가 선언됩니다. 포인터의 배열을 선언할 때와 다른 점은 *기호와 변수 이름을 괄호로 묶어준다는 것입니다. 포인터나 배열을 선안한 다음에 *나 [] 기호를 붙이면 연산자가 되지만, 변수를 선언할 때 사용된 *나 []기호는 연산자가 아니라 그저 포인터나 배열을 선언할 때는 이런 기호를 사용하자가 약속을 한 것이기 때문에 연산자 우선순위를 적용할 대상이 아닌 것입니다. 그냥 배열의 포인터를 선언할 때는 이렇게 하자고 약속을 한 것이라고 받아들이면 됩니다.
좌측 부분이 방금 선언한 배열의 포인터 입니다. 포인터가 가리키는 곳에는 char형 데이터 10개짜리 배열이 존재하게 됩니다. 배열 하나의 크기는 char형 데이터 10개로 고정되지만, 이것을 가리키는 포인터로 이러한 배열을 몇 개까지 가리킬 수 있는지는 제한이 없기 때문에 가로축으로는 고정 개수, 세로축으로는 가변 개수인 2차원 데이터를 다룰 수 있습니다.
배열의 포인터를 선언하면 메모리에는 단지 포인터 변수 1개가 생성될 뿐 실제 데이터를 저장하는 배열은 생성되지 않으므로, 배열에 해당하는 부분은 별도의 메모리 공간에 확보해야 합니다.
C. 2차원 포인터 – 포인터를 가리키는 포인터
Char **ptrPtr;
위와같이 하면 char형 포인터를 가리키는 포인터가 선언됩니다.
Char형 데이터는 char *형으로 가리킬 수 있고, char *형 데이터는 char **형으로 가리킬 수 있습니다. 따라서, 포인터의 포인터는 그림과 같은 형태로 가로축, 세로축으로 모두 가변 개수인 2차원 데이터를 다룰 수 있습니다.
다음엔 방금 설명한 포인터의 배열, 배열의 포인터, 그리고 2차원 포인터를 활용한 예제들을 보며 공부해 보겠습니다.
'Study' 카테고리의 다른 글
20121001_시스템엔지니어가 하는 일, 시스템엔지니어의 필요 지식 (0) | 2012.11.20 |
---|---|
20120718_2차원 데이터의 활용 (0) | 2012.11.20 |
20120712_1차원배열과 포인터(2) (0) | 2012.11.20 |
20120712_Java스터디 2일차 (0) | 2012.11.20 |
20120711_1차원 배열과 포인터 (0) | 2012.11.20 |