정의
배열은 요소(값 또는 변수)들이 연속적으로 저장되어있는 형태의 데이터 구조로, 인덱스 혹은 키로 요소를 참조할 수 있다.
ADT
배열은 요소(Element)를 가지며, 위 그림을 보면 요소들이 연속적으로 나란히 모여있는 모습을 볼 수 있다.
각 요소들은 위치를 가지고, 특정 요소에 접근하기 위해서는 인덱스(Index)를 통해 접근한다.
대부분의 프로그래밍 언어에서 배열 인덱스는 0부터 시작하며, 배열의 첫 번째 요소에 접근할 때에는 0번째 위치에 접근하는 형태가 된다.
또한, 앞서 확인한 그림은 1차원(선)적으로 데이터를 나열한 상태인데, 이를 중첩시켜 아래와 같이 더 높은 차원의 배열을 만들어 자료를 관리할 수도 있다.
배열의 경우 대부분의 프로그래밍 언어에서 기본적으로 지원하기 때문에 직접 구현할 필요는 없다.
개념을 어느 정도 익혔으니, C언어로 이동하여 배열을 직접 확인해보도록 하자.
배열 살펴보기
C언어에서 배열은 아래와 같이 선언한다. (T는 자료형을 나타낸다고 이해하자)
// T name[size];
int arr[8];
위 코드는 배열의 크기가 8인 int 형 배열 arr 을 선언한 코드이다.
변수 선언과 크게 다를건 없다. 단지 배열의 크기가 대괄호 안에 정의되어있다는 것뿐이다.
추가로 1차원(선) 배열 말고 다차원 배열도 아래와 같이 쉽게 선언할 수 있다.
int arr2[8][3]; // 8x3 크기의 2차원 배열
int arr3[8][3][3]; // 8x3x3 크기의 3차원 배열
...
몇 차원이든 배열 크기를 정의해주기만 하면 된다.
배열도 일반적인 변수와 동일하게 아래와 같이 선언과 동시에 값을 할당할 수 있다.
int arr[8] = {27, 3, 7, 120, 40, 8, 13, 9};
// 선언과 동시에 초기화 하는 경우 배열 크기를 생략해도 된다.
int arr[] = {27, 3, 7, 120, 40, 8, 13, 9};
// 다차원 배열은 아래와 같이 초기화한다. (3x3)
int arr2[][] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
(참고로 배열을 선언만 해둔 상태에서, 요소에 접근할 경우 메모리 상에 남아있던 쓰레기 값을 참조할 수도 있다)
우리가 선언한 배열 안에는 총 8개의 요소(int 형 값)가 들어있다.
배열의 요소는 인덱스를 통해 접근 가능하다고 앞서 설명했다. 이 또한 코드를 통해 살펴보도록 하자.
printf("%d", arr[2]); // 7
arr 배열의 2번째 인덱스 요소를 참조하여 출력하는 코드이다. 인덱스는 0부터 시작하므로 2번째 인덱스에 접근할 경우 3번째 값을 참조하게 된다. (다차원 배열도 동일하게 접근하면 된다.)
이번에는 배열 요소를 모두 출력해보도록 하자.
#include <stdio.h>
int main(void)
{
int arr[] = {27, 3, 7, 120, 40, 8, 13, 9};
for (int i = 0; i < 8; i++)
{
printf("%d %d\n", i, arr[i]);
}
return 0;
}
// Result
0 27
1 3
2 7
3 120
4 40
5 8
6 13
7 9
코드를 간략히 살펴보면, 선언한 배열 arr의 요소에 접근하고 출력하기 위해 for문을 활용했다.
for문에서 사용하는 변수 i 는 배열 인덱스 변수로써 사용되고 있다.
i는 0~7까지 증가하게 되고, 반복문 내에서는 arr 배열 요소에 접근하여 출력하고 있다.
더 알아보기
마지막으로 배열에 대해 조금 더 깊게 알아보도록 하자.
배열은 요소가 연속적으로 저장되어있는 형태의 데이터 구조를 갖고있다.
여러 요소를 담을 수 있는 배열의 크기가 어떤지 궁금하지 않은가?
한 번 아래 예제 코드를 통해 살펴보도록 하자.
#include <stdio.h>
int main(void)
{
int arr[] = {27, 3, 7, 120, 40, 8, 13, 9};
printf("%lu\n", sizeof(int));
printf("%lu\n", sizeof(arr));
return 0;
}
// Result
4
32
C언어에서는 sizeof 를 통해 자료형의 크기를 알 수 있다. 코드를 실행해보면 아래의 결과를 얻을 수 있다.
- int: 4바이트
- arr: 32바이트
4바이트로 정수값을 나타내는 자료형은 int 이다.
우리가 선언한 배열은 int 형 배열이므로 arr 의 크기는 int 형 크기 x 배열의 크기가 된다.
8개의 요소를 갖는 배열이므로, arr 배열의 크기는 4 x 8 = 32 바이트가 된다.
그렇다면 실제 메모리 공간 속에서 각 요소가 4바이트 크기를 가지고 있는지 확인해보자.
#include <stdio.h>
int main(void)
{
int arr[] = {27, 3, 7, 120, 40, 8, 13, 9};
for (int i = 0; i < 8; i++)
{
printf("%p\n", &arr[i]); // &는 메모리 위치를 반환한다.
}
return 0;
}
// Result
0x7ff7b855a6c0
0x7ff7b855a6c4
0x7ff7b855a6c8
0x7ff7b855a6cc
0x7ff7b855a6d0
0x7ff7b855a6d4
0x7ff7b855a6d8
0x7ff7b855a6dc
(C언어에서는 메모리 주소를 16진수로 표현한다)
출력된 결과를 살펴보면 각 요소가 4바이트의 간격을 유지하고 있는 것을 확인할 수 있다.
마무리하며
지금까지 배열에 대해 알아보았다.
여러개의 나열된 자료를 관리할 때 배열을 활용할 수 있고, 빈번하게 사용하는 자료구조이니 반드시 숙지해야한다.