배열은 번호가 붙은 칸 한 줄이다
지금까지 변수 하나에는 값 하나가 들어갔습니다. 학생 세 명의 점수라면 이렇게 됩니다.
int score1 = 90;
int score2 = 85;
int score3 = 78;
세 명이면 견딥니다. 백 명이면 변수가 백 개입니다.
평균을 구하려면 백 개를 전부 손으로 더해야 하고,
반복문으로 돌리고 싶어도 score1, score2 는 이름이라 번호로 셀 수가 없습니다.
앞에서 변수 이름은 컴파일이 끝나면 사라진다고 했습니다. 이름은 사람이 읽으려고 붙인 것이라 실행 중에 이름을 계산해서 만들 수는 없습니다.
이름 하나에 칸을 여러 개 붙이고, 칸은 번호로 꺼내는 것이 배열입니다.
배열은 이렇게 생겼다
int[] 는 “정수가 여러 개 들어가는 것” 이라는 타입입니다.
new int[5] 가 실제로 칸 다섯 개를 만듭니다.
값을 미리 알고 있으면 한 줄로 쓸 수 있습니다.
int[] scores = new int[] { 90, 85, 78 };
int[] scores = { 90, 85, 78 }; // 타입이 뻔하면 이렇게도 됩니다
칸 개수를 안 적었는데도 됩니다. 적어 준 값이 세 개니 칸도 세 개입니다.
칸에는 0부터 번호가 붙는다
앞에서 문자열의 인덱스를 봤습니다. 배열도 똑같습니다. 인덱스는 순번이 아니라 시작 지점에서 몇 칸 떨어졌는가입니다.
칸이 빈틈없이 붙어 있으니 몇 번째 칸이든 곱셈과 덧셈 한 번으로 찾아갑니다. 앞 칸을 하나씩 세지 않습니다. 첫 칸이든 백 번째 칸이든 걸리는 시간이 같습니다.
이게 배열의 가장 큰 성질입니다.
int[] scores = { 90, 85, 78 };
Console.WriteLine(scores[0]); // 90
Console.WriteLine(scores[2]); // 78
scores[1] = 100; // 쓰기도 됩니다
문자열과 다른 점이 여기입니다. 앞에서 문자열은 읽을 수만 있고 쓸 수 없다고 했습니다. 배열은 칸의 내용을 바꿀 수 있습니다. 못 바꾸는 것은 칸의 개수입니다.
만들면 칸에 기본값이 들어간다
앞에서 지역 변수는 값을 넣기 전에 쓸 수 없다고 했습니다. 배열은 다릅니다.
int[] scores = new int[3];
Console.WriteLine(scores[0]); // 0
에러가 아니라 0 이 나옵니다. new 로 자리를 잡을 때 그 자리를 전부 0으로 채우기 때문입니다.
| 타입 | 기본값 |
|---|---|
숫자 (int, double 등) |
0 |
bool |
false |
char |
번호 0번 문자 |
string 처럼 참조를 담는 것 |
null (아직 아무것도 안 가리킴) |
전부 비트가 전부 0인 상태입니다. 앞에서 본 대로 메모리에는 비트만 있고
그걸 무엇으로 읽을지는 타입이 정합니다. 0으로 채운 비트를 int 로 읽으면 0,
bool 로 읽으면 false 입니다.
Length 와 반복문
칸이 몇 개인지는 Length 로 알 수 있습니다.
int[] scores = { 90, 85, 78 };
for (int i = 0; i < scores.Length; i++)
{
Console.WriteLine(scores[i]);
}
앞에서 for (int i = 0; i < 길이; i++) 형태가 왜 굳어졌는지 이야기했습니다.
여기가 그 자리입니다. 인덱스가 0부터니 Length 미만까지 돌면 정확히 맞습니다.
<= 로 쓰면 마지막 한 바퀴에서 없는 칸을 건드립니다.
for (int i = 0; i <= scores.Length; i++) // i 가 3 일 때 터집니다
없는 칸을 건드리면 터진다
int[] scores = { 90, 85, 78 };
Console.WriteLine(scores[3]); // IndexOutOfRangeException
앞에서 정수가 넘칠 때는 예외도 경고도 없이 조용히 돌아간다고 했습니다. 배열은 반대입니다. 없는 칸을 건드리면 그 자리에서 프로그램이 멈춥니다.
조용히 넘어가는 것보다 낫습니다. 남의 메모리를 읽거나 덮어쓰면 훨씬 나중에, 전혀 관계없어 보이는 곳에서 이상하게 동작합니다. 그때는 원인을 찾을 수가 없습니다.
칸 개수는 나중에 못 바꾼다
배열의 한계가 여기 있습니다.
int[] scores = new int[3];
scores[3] = 100; // 칸이 없습니다. 늘어나지 않습니다
new int[3] 이 실행되는 순간 메모리에 세 칸 분량의 자리가 잡힙니다.
그 뒤는 다른 것이 쓰고 있을 수 있으니 뒤로 늘릴 수가 없습니다.
늘리려면 더 큰 배열을 새로 만들고 옮겨 담는 수밖에 없습니다.
int[] bigger = new int[6];
for (int i = 0; i < scores.Length; i++)
{
bigger[i] = scores[i];
}
scores = bigger;
앞에서 본 문자열 + 와 똑같은 구조입니다. 고치는 것처럼 보이지만 새로 만들고 옮기는 것입니다.
그래서 배열은 개수가 정해져 있을 때 씁니다. 요일 7개, 게임 판 9칸처럼요. 개수가 실행 중에 변하는 것은 배열로 다루기 번거롭습니다.
정리
- 배열은 이름 하나에 같은 타입의 칸을 여러 개 붙인 것입니다.
int[] a = new int[5];에서 대괄호가 배열 표시,new뒤의 숫자가 칸 개수입니다.- 칸에는 0부터 번호가 붙습니다. 인덱스는 시작 지점에서 몇 칸 떨어졌는가입니다.
- 칸이 붙어 있어서 몇 번째 칸이든 찾는 시간이 같습니다.
- 문자열과 달리 칸의 내용은 바꿀 수 있습니다. 못 바꾸는 것은 개수입니다.
- 만들 때 전부 기본값(비트가 0인 상태)으로 채워집니다.
- 없는 칸을 건드리면 예외가 나면서 멈춥니다.
- 칸 개수는 만든 뒤에 못 늘립니다. 늘리려면 새로 만들어 옮겨야 합니다.