주인장의 프로그래밍 개발 공부방

[Chapter 5 배열] 2. 배열의 구조 (feat. 1차원 배열) 본문

프로그래밍 기본 지식/Chapter 5 배열

[Chapter 5 배열] 2. 배열의 구조 (feat. 1차원 배열)

거신 2019. 8. 27. 09:09

지난 시간에는 배열이 왜 등장하게 되었는지와

일반 변수와 배열의 차이점에 대해서 간단하게 알아봤다.

이번 시간에는 배열을 선언하는 방법과 선언했을 때의 구조에 대해서 알아보려고 한다.

 

목표 : 배열을 선언하는 다양한 방법을 알 수 있고 배열을 선언했을 때 어떤 구조가 되는지 알 수 있다.

 

1. 배열의 선언방법

 

먼저 배열을 선언하는 방법에 대해서 알아보자.

참고로 배열을 선언한 변수는 참조 변수이기 때문에 값 자체가 아닌

주소를 저장하고 있다는 점을 기억하길 바란다.

굉장히 중요한 부분이다.

 

배열을 선언해보기에 앞서 다시 변수를 불러오려고 한다.

계속해서 변수를 끌어들이는 이유는 어찌되었든 변수에서 확장된 것이기 때문에

이해를 돕기 위해서 그러는 것이다.

 

int타입의 변수를 하나 선언해보겠다.

 

int i = 0;

 

이 한줄의 코드에 무슨 뜻이 담겨져 있는지는 여러분들이 너무나도 잘 알 것이라고 생각한다.

그런데 여기에서 이 코드를 이제 배열을 선언하는 코드로 바꿔보려고 한다.

 

int[] i = new int[n];

 

앞에서 변수를 선언한 코드에서 [ ](대괄호)를 더 붙여서 새로운 코드를 작성했다.

이 선언 방법이 바로 배열을 선언하는 방법이 되겠다.

그리고 기본형 변수와 달리 = 뒤에 new가 등장했기 때문에

여기에서 변수 i는 기본형 타입이 아닌 참조형 타입이라는 것을 알아채야 한다.

앞에서 잠깐 언급했지만 배열 변수는 참조형 변수이다.

 

다시 배열을 선언한 코드로 돌아와서 이제 세세하게 뜯어서 설명해보려고 한다.

 

(※참고 : 배열을 선언할 때 int i[] = new int[n];라고도 할 수 있는데 이 방법은 C언어에서 사용하는 방법이다.

자바에서도 사용은 가능하지만 int[]라고 사용하는데 알아보기에도 더 편하기 때문에

가능하다면 int i[]의 형태가 아닌 int[] i의 형태로 사용하길 권장한다.)

 

1) int[]

 

맨 앞에 등장한 기본형 타입 예약어 뒤에 [ ]를 붙인 것 뿐이다.

이 의미는 타입이 이제 int가 아니라 "int배열"이라는 뜻이 된다.

다시 말해, 지금 이렇게 선언한 변수가 일반적인 변수가 아니라 배열타입의 변수라는 의미이다.

그리고 int에는 int뿐만 아니라 double, char, long 뿐만 아니라

참조형 타입인 String도 가능하다.

(String 뿐만 아니라 어떠한 참조형 타입도 가능하다.)

즉, 자바 프로그래밍 안에서는 어떠한 타입도 배열로 선언할 수 있다는 소리가 되겠다.

 

하지만 여기에서 주의할 점이 있다.

int[]와 같이 이렇게 선언을 했다면

이 배열에 저장할 수 있는 값의 타입은 int타입만 가능하다.

다른 예로 String[]이라고 배열을 선언한다면

이 배열에는 String타입의 값만 저장이 가능하다는 뜻이 되겠다.

즉, int라고 적어둔 것은 int타입만 받겠다는 의미로 받아들이면 되겠다.

(물론 int, char와 같이 기본형 타입은 자동 형변환이 되기 때문에 형태는 달라지지만 저장은 가능하다.)

 

2) new int[n];

 

= 뒤에 등장하는 new int[n];는 우리가 잘 알고 있는

new String();과 같은 것이라고 생각하면 된다.

new 연산자는 메모리의 heap영역에 공간을 만들어두는 역할이고

그 공간에 우리가 앞서 만든 int[]의 형태의 방으로 만드는 것이다.

 

그리고 여기에서 [ ]안에 있는 n내가 생성할 배열의 방 개수를 의미한다.

예를 들어 n에 10을 넣는다면

new int[10];의 형태가 될 것이고 이 의미는 배열을 선언하는데

총 10개의 변수(값)를 저장할 수 있는 공간을 만들겠다는 뜻이 된다.

이를 앞으로 인덱스(index)라고 표현할 것인데 쉽게 생각해서 방을 10개 만든다고 생각하면 좋겠다.

 

이런식으로 배열을 선언하게 되면 빈 방이 n개가 생성이 되고 변수 i에는

new가 생성해낸 메모리 공간의 주소를 가지고 있는 형태가 된다.

String 변수와 동일한 구조를 지니고 있다고 생각하면 된다.

그리고 빈 방 안에는 해당 배열 타입의 기본값이 자동으로 저장되는데

여기에서는 타입이 int[]타입이기 때문에 int의 기본값인 0이 자동으로 방마다 저장이 된다.

 

2. 배열의 구조

 

그림으로 그려보면 이러한 형태가 된다는 것을 알 수 있다.

 

그림1)

int[] i = new int[4]; 로 배열 선언 시

배열은 기본적으로 연속된 방처럼 되어 있고 여기에 인덱스라는 방 번호를 부여받게 된다.

인덱스는 0부터 시작해 사용자가 지정한 방 개수의 -1까지 부여가 된다.

위의 그림1에서는 방 개수를 4개로 지정했기 때문에

인덱스가 0번부터 4-1번인 3까지 지정된 것이다.

(프로그래밍에서는 숫자가 항상 0부터 시작한다는 것을 잊지말자.)

이렇게 만들어진 방에는 선언만 한다면 기본값이 자동으로 들어가서 초기화가 되는데

지금은 int[] 타입이기 때문에 0이 들어가있는 모습이다.

그리고 계속해서 언급하지만 변수 i참조형 변수이기 때문에

heap영역에 생성된 배열의 메모리 주소를 가지고 있다는 점도 잊지 말자.

 

그리고 그림의 배열 형태가 가장 기본적인 배열의 형태인데

이걸 우리는 1차원 배열이라고 한다.

1차원이 있다면 2차원도 있고 3차원도 있다는 말일텐데

이 다음에 배우게 될테니 지금은 1차원 배열의 형태라는 것만 기억하면 좋겠다.

어차피 다음 포스트에서 2차원 배열을 만나게 될 것이다.

 

3. 배열의 방 찾아가기

 

배열을 선언하는 방법과 구조가 어떻게 생기는지에 대해서 알아봤는데

그렇다면 도대체 배열의 각 방은 어떻게 찾아가야 되는걸까?

 

일단 그림1과 같이 배열이 선언이 되어 있다면

여기에 배열의 각 방에 대한 변수도 함께 선언이 된다.

무슨 말이냐면 각 방을 가리키는 변수가 만들어진다는 것이다.

간단하다.

배열을 가리키는 변수명 뒤에 [ ]와 해당하는 인덱스 번호를 적어주면 끝이다.

즉, 현재 그림에서 만약 인덱스 2번의 방을 찾아가겠다면

i[2]인덱스 2번의 변수가 되는 것이다.

여기에서 주의할 부분이 발생한다.

바로 변수의 타입이 되겠다.

 

현재 i의 타입은 int[]로 배열타입이다.

그런데 방을 가리키는 변수 i[2]는 타입이 int[]이 아니라 int가 되는 것이다.

배열의 방 안에 저장되어 있는 값의 타입이 int이기 때문에

이제 이 방을 가리키는 변수의 타입은 int가 된다는 것이다.

처음 배열을 접한다면 이 부분에서 헷갈리는 사람이 다소 있을 것이라 예상된다.

그런데 이 부분을 정확하게 알고 있어야 나중에 나오는

2차원 배열이라는 것을 제대로 이해할 수 있다.

 

그렇기 때문에 i[2]를 사용한다면

우리가 기본형 변수에 값을 저장하는 것처럼 사용이 가능하다.

위의 예시에서 i = 2;는 절대 불가능하지만

i[2] = 2;는 가능하다는 뜻이다.

 

4. 배열을 선언하는 다른 방법들

 

앞서 우리가 알아봤던 배열의 선언방법은 어디까지나 기본적인 방법이다.

배열을 선언하고 생성하는 방법에는 여러 방법이 존재하는데

이 방법들은 개인이 선택해서 편한 것을 사용하면 되겠다.

 

1) int[] i = new int[5];

 

예시부터 봤던 선언 방법이다.

이 방법은 우리가 배열을 선언하고 선언한 배열의 방에

자동으로 기본값이 저장되는 과정까지 실행된다.

여기에서는 직접 값을 저장하지 않기 때문에

나중에 원하는 값을 저장하는 과정이 필요하다.

 

2) int[] i = new int[] {1, 2, 3, 4, 5};

 

이 방법은 배열 선언과 동시에 배열의 방에 기본값이 아니라

우리들이 원하는 값을 바로 저장해서 초기화하는 방법이 되겠다.

그런데 잠깐 눈여겨 봐야되는 부분은

new int[]에 원래는 [ ]안에 배열의 방 개수를 적어줘야했지만

이렇게 바로 값을 넣어서 초기화할 때는 방 개수를 적어주면 에러가 발생한다.

그래서 뒤에 { }(중괄호)를 붙이고 값을 적어주면

자신이 입력한 값의 개수만큼의 방이 자동으로 생성된다.

위의 예시라면 배열의 방이 5개가 생성이 되고 0번 방에는 1, 1번 방에는 2와 같이

순서대로 값이 저장되는 것이다.

 

물론 new int[] {};와 같이 아무것도 입력하지 않아도 가능하다.

이 코드는 값을 집어넣지도 않았다는 것이지만

방도 생성하지 않았고 단순히 참조형 변수만 생성한 것이 되기 때문에

이 배열을 사용하기 위해서는 다시 한 번 초기화를 하는 과정을 거쳐야 한다.

사실 한 번에 할 일을 두 번 이상해야되기 때문에 이렇게는 사용하지 않는 것이 좋겠다.

 

3) int[] i = null; (또는 int[] i;)

i = new int[5];

 

이 방법은 앞의 선언 방법들을 두 번의 과정으로 나눈 방법이 되겠다.

일단 변수를 선언만 하고 그 다음에 배열의 방 개수를 정하고 값을 저장하는 방법이다.

i에 null을 넣게 되면 메모리의 heap영역에서 생성하지 않고

참조형 변수 i만 선언하는 형태가 되는데

생각해보면 2)에서 일을 두 번하는 것이기 때문에 비효율적인 것이 아니냐라고 생각할 수 있겠지만

자바와 같이 객체지향 프로그래밍에서는

이렇게 변수를 선언만 해두고

다른 위치에서 초기화를 하는 방법을 많이 사용하기 때문에

나중에 중고급 프로그래밍을 공부하다보면 가끔씩 만나게 될 것이다.

지금은 이렇게도 선언할 수 있다라고만 알고 있으면 좋겠다.

 

5. 마무리

 

배열int[] i = new int[n];과 같이 선언하는데

여기에서 int[]은 우리가 흔히 알고 있는 int, char, String과 같이

변수의 타입이 되겠다.

여기에서는 배열 타입이라고 하는데 int[]라고 선언을 했다면

이 배열에는 int타입의 값만 저장할 수 있다는 뜻이 된다.

그리고 i는 값 자체가 저장되는 것이 아니라 heap영역에 생성된

배열의 주소를 저장하고 있는 참조형 변수라는 것도 잊지말자.

배열은 큰 영역 안에 연속되는 방으로 이루어져 있는데

이 방은 앞서 배열을 선언할 때 [ ] 안에 입력하는 n에 따라서 달라진다.

그리고 방의 번호들을 인덱스(index)라고 부르고 인덱스0번부터 시작해 n-1번까지 지정된다.

그리고 배열에서 값이 저장되어 있는 각 방을 찾아가기 위해선

배열의 변수인 i 뒤에 [index]를 붙여서 찾아갈 수 있는데

1번 인덱스를 찾아가겠다면 i[1]과 같이 적으면 된다.

그런데 여기에서 ii[1]의 타입이 다른데

i는 int[]로 배열 타입이고 i[1]는 int타입이라는 것을 잊지말자.

마지막으로 배열을 선언하는 방법에는

int[] i = new int[5];

 

int[] i = new int[] {1, 2, 3, 4, 5};

 

int[] i = null;

i = new int[5];

 

와 같이 다양한 방법들이 존재한다.

Comments