배열은 자료들의 나열입니다. C언어에서는 데이터들의 나열이 되겠습니다. 예를 들어 어떤 학교 모든 학생의 이름, 성별, 전화번호를 데이터로 저장할 때에 각 학생마다 별개의 변수로 선언하려면 지루한 작업이 될겁니다. 하지만 배열을 배우고 나면 이러한 데이터를 하나로 묶어서 처리할 수 있게 되고 코드의 작성이 훨씬 간편해집니다.


1. 배열의 구조


가장 기본이 되는 배열의 선언 방법부터 봅시다.

#include <stdio.h>

int main(void)
{
    //방법 1 : 선언 & 초기화
    int arr[4] = {11,22,33,44};

    printf("%d\n",arr[0]);
    printf("%d\n",arr[1]);
    printf("%d\n",arr[2]);
    printf("%d\n",arr[3]);

    return 0;
}

실행결과

11

22

33

44

계속하려면 아무 키나 누르십시오 . . .


위는 가장 기본적인 배열의 선언 방법입니다. [4]라는 대괄호[ ]안의 숫자와, 한 번에 여러 숫자가 중괄호{ }에 쌓여서 대입이 됩니다.

1-8

배열이 선언이 되기 위해서는 3가지의 정보가 필요합니다.

  • 배열의 자료형 : 배열에 담을 변수들의 자료형을 결정
  • 배열의 길이 : 배열에 담을 데이터의 갯수
  • 배열의 이름 : 배열이 할당되는 메모리공간에 접근하기 위해 변수와 같이 이름 필요


배열의 각 원소(element)에 접근하기 위한 index는 1이 아닌 0부터 시작합니다. 따라서 길이가 n인 배열은 0부터 n-1의 index 값 까지 가지고 있습니다. arr는 길이가 4인 배열이므로 첫 번째 원소는 arr[0]으로 접근하고,두 번째 원소는 arr[1], 이후로 arr[2], arr[3] 까지 있습니다. arr 배열에 대해 정리하자면 'int 자료형의 원소를 가지는 길이가 4인 배열' 입니다. 그림으로 표현하면 다음과 같습니다.

2-2


배열이 메모리에 저장되는 방식은 다음과 같습니다.

  1. 배열의 각 자료에는 index를 사용해 접근한다. 배열의 index는 0부터 시작한다. 원소가 n개인 배열이면 0부터 (n-1)까지
  2. 배열의 각 자료는 물리적으로 연속된 메모리공간에 저장된다.
  3. 메모리에는 주소가 1byte마다 부여되므로 이웃한 자료형의 주소값은 자료형의 크기만큼 차이난다.

위 예제의 경우에 각 데이터는 첫 번째 원소인 11부터 44까지 차례대로 연속된 메모리공간을 차지합니다. 각 변수들은 int형이므로 메모리를 4byte만큼 차지합니다.


2. 배열 선언방법들


C언어는 배열을 선언함에 있어 유연한 프로그래밍을 위해 다양한 선언 방법을 제공합니다.

#include <stdio.h>

int main(void)
{
    //방법 2 : 선언을 먼저 하고 이후에 초기화 (초기화 전까지는 쓰레기값이 담겨있다.)
    int arr[3];

    printf("%d\n", arr[0]);
    printf("%d\n", arr[1]);
    printf("%d\n", arr[2]);

    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;

    printf("%d\n", arr[0]);
    printf("%d\n", arr[1]);
    printf("%d\n", arr[2]);

    return 0;
}

실행결과

-858993460

-858993460

-858993460

1

2

3

계속하려면 아무 키나 누르십시오 . . .


위와 같이 배열을 초기화 없이 선언 해줄 수도 있습니다. 단, 초기화를 시키지 않았기 때문에 각 배열의 원소에는 임의의 쓰레기값이 저장됩니다. 이후 배열에 index를 사용해서 데이터를 저장할 수 있습니다. 이처럼 우리는 배열의 각 원소를 하나의 변수처럼 취급할 수 있게 됩니다.


#include <stdio.h>

int main(void)
{
    //방법 3 : 길이정보 주지않고 나열하면 길이정보 자동 생성
    int arr[] = {1,2,3,4,5,6,7,8};
    printf("The length of arr : %d\n", sizeof(arr)/sizeof(int)); //sizeof 연산자는 변수나 배열의 byte크기를 return

    return 0;
}

실행결과

The length of arr : 8

계속하려면 아무 키나 누르십시오 . . .


길이정보를 명시하지 않고 초기화를 하면서 배열을 선언하면 저장한 데이터의 갯수로 배열의 길이가 결정 됩니다.

sizeof 연산자는 변수나 배열의 byte 크기를 알려주는 연산자 입니다. sizeof(arr)/sizeof(int)의 계산결과를 이용해 arr의 길이(데이터의 갯수)를 구했습니다. sizeof(arr)는 배열 arr의 총 byte크기이고 sizeof(int)는 배열 arr의 각 원소의 byte 크기입니다. 따라서 위의 계산결과는 배열 arr의 길이, 즉 데이터의 갯수를 반환합니다.


#include <stdio.h>

int main(void)
{
    //방법 4 : 명시한 배열 길이보다 적은 데이터를 넣어주면 남는 원소에는 자동으로 0이 저장
    int arr[10] = {1,2,3};
    int i;

    for(i = 0; i < (sizeof(arr)/sizeof(int)); i++)
    {
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    return 0;
}

실행결과

arr[0] = 1

arr[1] = 2

arr[2] = 3

arr[3] = 0

arr[4] = 0

arr[5] = 0

arr[6] = 0

arr[7] = 0

arr[8] = 0

arr[9] = 0

계속하려면 아무 키나 누르십시오 . . .


길이는 10인 배열을 선언하면서 { }안에 초기화 데이터는 3개밖에 넣어주지 않았습니다. 그러자 앞의 원소부터 차례대로 1, 2, 3이 담기고 나머지 원소의 값은 모두 0이 되었습니다. 배열의 길이보다 초기화 데이터의 갯수를 작게 넣어주면 앞에서부터 차례대로 초기화 시키고 나머지 원소들의 값은 자동으로 0으로 초기화 됩니다.

여러가지 배열 선언 방법에 대해 알아보았는데, 상황에 따라서 유연하게 사용하시면 됩니다.

그런데 만약 배열 길이를 초과한 갯수의 데이터를 넣어주면 어떻게 될까요?

#include <stdio.h>

int main(void)
{
    int i;
    int arr[5];

    arr[0]=0;
    arr[1]=1;
    arr[2]=2;
    arr[3]=3;
    arr[4]=4;
    arr[5]=5;
    arr[6]=6;
    arr[7]=7;
    arr[8]=8;
    arr[9]=9;

    for(i = 0; i<10; i++)
    {
        printf("arr[%d] = %d\n",i, arr[i]);
    }

    return 0;
}

실행결과

arr[0] = 0

arr[1] = 1

arr[2] = 2

arr[3] = 3

arr[4] = 4

arr[5] = 5

arr[6] = 6

arr[7] = 7

arr[8] = 8

arr[9] = 9

계속하려면 아무 키나 누르십시오 . . .


배열의 길이를 초과한 index를 사용하여 배열에 접근을 시도했는데도 에러가 나지 않습니다. 컴파일러는 배열에 관해서 유효성검사를 하지 않습니다. 따라서 이러한 오류를 잡아내지 못합니다. 프로그램이 arr[5]~arr[9]의 번지수에 해당하는 메모리공간을 활용하지 않는 경우라면 큰 문제가 되지 않을 수 있지만 메모리 침범은 예상할 수 없는 에러를 발생시킬 확률이 높기 때문에 절대 피해야 합니다.

+ Recent posts