관리 메뉴

Kim's Programming

C언어 - 배열(Array)(2/2) 본문

Programming/C

C언어 - 배열(Array)(2/2)

Programmer. 2015. 8. 15. 12:57

초기식


배열을 선언과 동시에 초기화할 때는 초기값의 개수가 배열 크기와 일치하는 것이 가장 이상적입니다.

int ar[5] = {4,8,3,69,-7}

ar 배열의 크기가 5이기 떄문에 { }괄호 속에 있는 초기값도 다섯개를 지정하였습니다. 모든 초기식이 다 이렇게 작성이 된다면 문제가 없습니다. 배열의 크기가 작다면 초기값을 다 적는 것이 별로 어렵지 않습니다. 그러나 배열이 엄청나게 크다면 그 초기값을 일일이 나열하기가 귀찮아 지고 타이핑 시간만 엄청나게 길어집니다.

int ar[1000] = {1,2,3,4,0,0,0,0,0,.......................................하...}

이번 ar배열은 크기가 1000인데 앞 쪽 네 개만 1,2,3,4,로 초기화를 시키고 나머지 전부를 0으로 초기화 하고 싶다고 했을때 는 괄호를 열고 1,2,3,4,를 치고 996개의 0을 입력해주어야 합니다. 이걸 다 칠려고 하면 엄청나게 끔찍하게 고통스러울 겁니다. 하지만 C에서는 초기값이 배열 크기보다 적을 경우엔 나머지 배열 요소들을 전부 0으로 초기화를 해줍니다. 특별히 몇개만 지정해서 나머지도 초기화가 가능합니다. 초기화에서는 이런 훌륭한 기능이 있습니다.


int ar[1000] = {1,2,3,4}


이렇게 쓰면 앞쪽 네 개 요소만 1,2,3,4으로 초기화하고 ar[4]~ar[999] 까지 모두 0으로 초기화합니다. 이런 초기식이 다소 혼란스러워 보일 수도 있으므로 초기식에  {1,2,3,4,}와 같이 마지막에 콤마를 하나 더 붙여서 나머지가 0으로 초기화 임을 표시하는 방법을 쓰게 됩니다. 다음 3가지 선언의 차이를 알아보겠습니다.

1
2
3
int ar[1000];
int ar[1000]={0};
int ar[1000]={0,};
cs

첫번째 줄과 같이 선언만 한 경우는 배열의 모든 요소들이 쓰레기 값을 가지지만 두번째 줄과 같은 형태나 세번쨰 같은 형태를 띄면 모든 배열 요소가 0으로 초기화됩니다. 지역 배열을 전역 배열처럼 초기화하고 싶다면 선언문 다음에 ={0}만 붙여주면 됩니다. 하지만 배열 중간부분은 모두 0 으로 하고 뒷부분의 일부만 원하는 값으로 초기화 하는 방법은 제공되지 않습니다. 그래서 ar 배열을 전부 초기화 하되 ar[830]만 120으로 초기화 하고 싶으면 다음과 같이 하는게 맞습니다.

1
2
int ar[1000= {0,};
ar[840]=120;
cs

위와 같이 전부 0으로 초기화 한뒤 원하는 배열 요소에만 별도로 대입하는 형태입니다. 다음으론 반대로 초기값이 배열 크기보다 많은 경우를 살펴보겠습니다.

1
int array[5]={1,2,3,4,5,6};
cs

배열의 크기는 5인데 초기값 갯수는 6개입니다. 이 코드를 컴파일 하게되면 too many initializer  에러로 처리됩니다.

 

즉, 초기값이 너무 많다는 이야기 입니다. 초기값이 남는 경우는 99.9% 오타가 원인인데 같은 값을 반복해서 입력했다거나 콤마가 하나더 삽인된 경우입니다. 하지만 배열의 크기가 크고 초기값이 많으면 입력하기가 쉽지 않아서 실수할 경우가 많아집니다. 이럴 떄는 초기식의 개수를 잘 세어보고 잘못 입력된거나 한걸 살펴보고 남는 초기값을 지워야합니다. 컴파일러가 초기식이 부족하면 말없이 0으로 초기화 시켜주지만 남는 경우는 무조건 에러로 처리해버립니다. 에러가 출력되는 이유는 기억공간이 부족해서 다 넣을 수도 없으며 심각한 문제를 유발하기 떄문입니다. 왜냐하면 만약 ar[3]에 값을 중복으로 넣었으면 ar[3]부터는 전부 하나씩 밀려서 죄다 잘못된 값이 들어가게 됩니다. 배열 선언문이 초기식을 가질 떄는 배열의 첨자크기를 생략할 수 있습니다. 네개의 초기값을 가지는 ar배열은 다음과 같이 선언하면 됩니다.

1
int array[]={1,2,3,4};
cs

컴파일러는 이 선언문의 초기식을 보고 개발자가 ar 배열 크기로 4를 원한다는 것을 판단합니다. 따라서 배열의 크기를 생략해도 array라는 배열의 크기는 자동으로 4가 되며  이배열을 위해서 16바이트의 메모리가 할당 될 것입니다. 배열 크기를 생략하면 초기값의 개수가 아주 많을 때 일일이 초기값의 갯수를 세어 보지 않아도 되고 차후에 초기값이 늘어나도 그에 맞게 배열 크기도 자동으로 조정되므로 편리합니다. 실제로 할당된 크기는 sizeof 연산자를 이용해서 구할 수 있습니다. 배열을 초기화 하는 방법이 간단히 정리하면 다음과 같습니다.

 배열의 크기(개수)와 초기값의 개수

 결과

 같다

 문제 또는 다른 처리 없음

 초기값이 적을때

 입력되지 않은 초기값 0으로 처리, 단 앞에만 입력가능

 배열의 크기가 적을때

 에러처리 컴파일 안됨

 배열의 크기 생략

 배열 크기가 초기값에 따라 크기 할당

 

2차 배열 초기화

 

2차원 이상의 다차원 배열을 초기화하는 방법도 1차원 배열과 비슷하지만 차원이 높아지므로 다양한 초기화 방법이 존재합니다. 차례 차례 알아보겠습니다 배열은 array[3][3];을 이용하겠습니다.

  1. 초기값 개수가 꼭 맞는 경우

    배열 크기와 초기값 개수가 일치하면 가장 자연스럽습니다. { } 괄호 안에 초기식을 나열하기만 하면 됩니다. array배열의 총 크기는 3*3=9이므로 아홉 개의 초기값을 적어주면 됩니다.

    1
    int array[3][3]={1,2,3,4,5,6,7,8,9};
    cs

    선언문에 따라서 array배열은 ar[0][0]부터 [3][3]까지 차례 차례 순차적으로 채워지게 됩니다.(앞에 메모리가 1차원 공간이기 때문에 저장되는 순서와 같이 들어가게 됩니다.) 하지만 이렇게 나열을 하게되면 어디서 부터 어디까지가 어느행을 뜻하는지 헷갈리기 떄문에 행별로 묶어보는 방법도 생각할 수 있습니다.

    1
    int array[3][3]={{1,2,3},{4,5,6},{7,8,9}};
    cs

    {1,2,3}이 첫행이고 그 다음으로 두 번쨰 세 번째행입니다. 가시적으로 확인이 쉽게 되기 때문에 초기값을 수정하기엔 너무 쉽습니다. 만약 이 배열이 엄청나게 많은 초기 값이 선언이 되어 있는 배열에서 특정한 위치를 찾는 것은 아주 힘듦니다. 또 이렇게 나누는것 뿐만아니라 개행도 같이 이용을 해주면 더욱더 구별하기 좋아집니다.

    1
    2
    3
    4
    5
    int array[3][3]={
        {1,2,3},
        {4,5,6},
        {7,8,9}
    };
    cs

    소스가 조금 길어지는 단점은 있지만 2차원적인 배열의 형태를 더 확실하게 볼 수 있습니다. 이렇게 하면 아주 많은 경우에도 문제없이 특정 요소를 찾아서 수정을 할 수 있습니다.

  2. 초기값이 모자랄 때

    특정행의 나머지 요소를 모두 0으로 초기화할 때는 0을 일일이 밝히지 않아도 됩니다. 만약 첫 행에서만 첫 번쨰 이후 요소가 전부 0이라면 다음과 같이 초기화를 하면됩니다.

    1
    in array[3][3]={{1},{4,5,6},{7,8,9}};
    cs

    이 선언문은 1행에서 비어있는 1행쪽 { } 괄호가 비어있는 만큼 0으로 초기화 시깁니다. 2행과 3행은 여전히 개수가 맞기 떄문에 여전히 다 채워집니다.

    array[0][0]=1

    array[0][1]=0

    array[0][2]=0

    array[1][0]=4

    array[1][1]=5

    array[1][2]=6

    array[2][0]=7

    array[2][1]=8

    array[2][2]=9

    첫번째 행의 값이 한개 밖에 없기 떄문에 나머지 부분은 모두 0이 될 것이고 두 번째나 세 번째의 경우는 초기값이 모두 있으므로 순서대로 초기화가 되게 됩니다. 가장 좋은 방식은 1뒤에 콤마를 하나 붙여서 뒤에는 0이라는 것을 표기해주는 것입니다. 물론 콤마를 붙인다고 해도 컴파일러는 무시합니다. 다른 사람이 봤을때 이해하기 좋게 붙여 주는 것입니다. 이번엔 또 다른 경우를 해보겠습니다.

    1
    in arry[3][3]={1,2,3,4,5};
    cs

    다음의 경우는 조금 다릅니다. 중괄호가 없기 때문에 초기식에 나타나는 순서대로 배열 요소를 채워 나가다가 남은 요소를 0으로 초기화하므로 0이 되는 배열 요소가 달라집니다. 앞에 있는 5개 array[0][0]~ar[1][1]까지만 채워지고 나머지는 0으로 초기화가 됩니다.

    array[0][0]=1

    array[0][1]=2

    array[0][2]=3

    array[1][0]=4

    array[1][1]=5

    array[1][2]=0

    array[2][0]=0

    array[2][1]=0

    array[2][2]=0

    중간에 있는 행의 나머지 요소에 대한 초기값을 생략할 때는 행단위로 중괄호를 반드시 써야합니다.

  3. 초기값 갯수가 남는 경우

    1차원 배열에서와 마찬가지로 초기값이 남으면 too many initializer에러를 볼 수 있습니다. 됩니다. 다음과 같은 경우는에러처리됩니다.

    1
    int array[3][3]={{1,2,3,4},{1,2,3},{1,2,3}}
    cs

    이 선언문은 1행에 3개만 들어갈 수 있는 공간 뿐인데 초기값에서는 4개를 넣게 선언 되었으므로 에러처리 됩니다.

  4. 배열의 크기를 생략하는 방법

    2차원 배열도 1차원 배열과 마찬가지로 배열의 크기를 생략할 수 있되 1차 첨자의 크기만 생략가능하며 나머지 첨자는 반드시 밝혀야 합니다.

    1
    int array[][2]={{1,2,3},{1,2,3}};
    cs

    1차 첨자의 크기를 생략해도 행이 두 개임이 명백하기 떄문에 컴파일러는 1차 첨자 크기가 2이라는 것을 알 수 있습니다. 열의 개수가 3개임을 명백하게 밖혀 주었으므로 세 개씩 묶어 보면 필요한 행의 개수가 자동으로 계산이 되게 됩니다. 또 중괄호가 없어도 배열 크기 계산은 문제가 없습니다. 이 상태에서 행을 더 늘리고 싶으면 초기식을 더 적어주면 알아서 늘어나게 됩니다.

    만약 열의 개수를 안밝혀 준다면 어떤 일이 있어 날까요? 또 왜 넣어줘야 하는 걸 까요?

    1
    int array[][]={1,2,3},{1,2,3}};
    cs

    다음과 같은 배열을 선언하게 되면 경우의 수가 생기게 됩니다. 다음의 배열은 1행 6열도, 2행 3열도, 3행 2열도, 6행 1열도 가능하게됩니다.  이렇기 때문에 열 하나를 잡아주어 경우의 수가 생김을 막아 주는 것입니다.




'Programming > C' 카테고리의 다른 글

C언어 - 포인터(Pointer)(2/3)  (1) 2015.08.18
C언어 - 포인터(Pointer)(1/3)  (2) 2015.08.16
C언어 - 배열(Array)(1/2)  (0) 2015.08.13
C언어 - 표준 함수  (0) 2015.08.11
기억 부류(Storage Class) (2/2)  (0) 2015.08.10