💡 정의
배열은 요소(값 또는 변수)들이 연속적으로 저장되어있는 형태의 데이터 구조로, 인덱스 혹은 키로 요소를 참조할 수 있다.
🌱 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바이트의 간격을 유지하고 있는 것을 확인할 수 있다.
지금까지 배열에 대해 알아보았다.
여러개의 나열된 자료를 관리할 때 배열을 활용할 수 있고, 빈번하게 사용하는 자료구조이니 반드시 숙지해야한다.