본문 바로가기
프로그래밍/C언어

c언어 - 배열

by solution online 2023. 8. 13.
728x90
반응형

배열부터가 조금 신경써서 봐야할 내용입니다.

앞서 진행한 내용들은 입문에서 다소 가볍게 보셔도 되는 내용입니다.

 

앞으로 진행할 배열과 포인터는 중요하다고 볼 수 있는데요.

이유는 배열, 포인터 사용에 메모리 사용법이 필수이고, 그에 따라 메모리 주소가 어떻고 저떻고 나오기도 하고

실무에서 실수하면 각 종 버그는 물론이고, 알 수 없는 이유로 프로그램이 죽는 이유가 생기기 때문입니다.

 

현재 입문을 기준으로 설명드리기에 실무에까지 적용될 내용은 진행되지 않겠지만

개념과 사용법은 꼭 알아두시는 것이 좋습니다.

 

 

배열

사전적 의미로는 "일정한 차례나 간격에 따라 벌여 놓음." 이라는 뜻 입니다.

컴퓨터 용어에서의 배열을 다시 얘기해 본다면 "번호와 번호에 대응하는 데이터들로 이루어진 자료구조" 라고 할 수 있겠습니다.

 

번호라는 용어는 잘 안쓰이고 인덱스(Index) 라는 용어를 자주 쓰는데요.

배열을 설명할 때 표를 자주 사용합니다.

 

우선 코드로 살펴보죠.

#include <stdio.h>

int main(void)
{
        char array[5];
        char array2[5] = {'a', 'b', 'c', 'd', 'e'};
        char array3[5] = {'a'};
        int cnt = 0;

        array[0] = '1';
        array[1] = '2';
        array[2] = '3';
        array[3] = '4';
        array[4] = '5';

        for (cnt=0 ; cnt < 5 ; cnt++)
        {
                printf("array[%d]: %c\n", cnt, array[cnt]);
        }

        for (cnt=0 ; cnt < 5 ; cnt++)
        {
                printf("array2[%d]: %c\n", cnt, array2[cnt]);
        }

        for (cnt=0 ; cnt < 5 ; cnt++)
        {
                printf("array3[%d]: %c\n", cnt, array3[cnt]);
        }

        printf("array2: %s, %p\n", array2, array2);
        printf("array3: %s, %p\n", array3, array3);

        array3[0] = 'f';
        printf("array2: %s, %p\n", array2, array2);
        printf("array3: %s, %p\n", array3, array3);

        array2[4] = '\0';
        printf("array2: %s, %p\n", array2, array2);


        return 0;
}
반응형

 

뭔가 길죠!?

일부러 한번에 여러 예제를 보여 드리려다 보니 반복해서 써놓은 것들이 있습니다.

 

배열을 영어로 array 라고 자주 사용합니다.

그래서 변수명은 array라고 했고요.

 

문자형 배열을 array, array2, array3 총 3개 만들었습니다.

 

선언을 3개나 한 이유는?

초기화 방식을 보여드리기 위해 한 것 입니다.

array[5]; 아무것도 대입시키지 않아도 되고요.

array2[5]; 직접 대입해도 되고요.

array3[5]={'a'}; 원하는 만큼만 대입해도 됩니다.

 

변수 선언할 때 [5] 라고 썼는데요.

이것은 5개 배열을 만들라고 선언한 것 입니다.

쉽게 얘기하면 5개의 칸을 만들라고 한 것이죠.

 

따라서 구조는 아래  처럼 5개의 칸이 생기는 것 입니다.

         

array2 로 예를 들면 아래와 같습니다.

a b c d e

그런데 변수 선언 후에 array 배열에 하나씩 값을 대입시키는 것이 보이시나요?

선언할 때는 [5] 라고 썼는데 실제 값은 [0] ~ [4] 에 대입시키죠!?

 

배열은 5개지만 컴퓨터는 0부터 시작하기 때문에 0~4의 번호(index)를 사용한 것 입니다.

 

프로그래밍할 때 이 부분이 입문할 때 자주 혼동되는 경우가 많습니다.

숫자의 시작은 0부터! 왜? 만든 사람들이 그렇게 정했다! ㅎㅎ

 

for문은 각 배열 변수들의 내용을 보여주기 위해서 사용했습니다.

array[0]: 1
array[1]: 2
array[2]: 3
array[3]: 4
array[4]: 5
array2[0]: a
array2[1]: b
array2[2]: c
array2[3]: d
array2[4]: e
array3[0]: a
array3[1]:
array3[2]:
array3[3]:
array3[4]:
array2: abcdea, 0x7fffd8a8dede
array3: a, 0x7fffd8a8dee3
array2: abcdef, 0x7fffd8a8dede
array3: f, 0x7fffd8a8dee3
array2: abcd, 0x7fffd8a8dede

결과물을 볼까요?

 

흠... 혹시 이상한점을 발견하셨나요?

 

array2: abcdea, 0x7~

이라는 부분 보이시나요?

 

앞서 5개의 칸을 가진 배열을 선언했다고 했습니다.

그런데 결과는? abedea 6개가 나오죠?

 

결과부터 말씀드리면 array3의 a가 나온 것 입니다.

왜???

 

초반에 언급을 했습니다.

메모리 사용법을 아셔야 한다고요.

코딩은 RAM을 사용합니다. RAM 즉 메모리의 공간을 사용하죠.

각 변수들은 RAM의 어느 한 곳의 공간을 사용합니다.

 

코딩을 하시려면 메모리 구조가 어떻게 되는지 기본을 아셔야 합니다.

bit, byte 단위도 아셔야 하고, 메모리는 몇 바이트로 구성되어 사용되는지?

비트별로 어떻게 사용되는지? 등등

 

우선 array2의 메모리 주소를 보여드리기 위해 printf에 %p 를 사용했습니다.

해당 출력자로 메모리 주소를 볼 수 있고, array2의 메모리 주소는 0x7fffd8a8dede 입니다.

 

참고로 16진수도 익숙해 지셔야 합니다.

0x 로 시작하는 것은 16진수를 뜻 합니다.

0~15를 하나로 사용하는 것인데 0~9, a, b, c, d, e, f 요렇게 16개를 사용합니다.

그래서 주소에 숫자도 있고 a~f도 있는 것 입니다.

 

복잡하죠? ㅎㅎ

일단은 그렇구나~ 하고 알아두시면 될 것 같습니다.

 

다시 돌아와서 array2 출력 했는데 array3의 값까지 나왔습니다.

잘 보시면 printf에 array2 배열 출력을 위해 %s 를 사용했습니다.

이는 문자열을 출력하기 위해 사용되는 것 입니다.

 

제가 문자형 배열을 만들었죠?

해당 문자형 배열 변수를 한번에 출력하기 위해 %s를 쓰기도 합니다.

 

그러나 이는 매우 조심해야할 방식입니다.

 

왜냐? 우리가 그냥 문자열을 쓸 때는 abcde 라고 쓰지만

컴퓨터는 이게 문자형인지 정수형인지 문자열인지 알 수가 없습니다.

그래서 문자열 구분을 위해 맨 끝에 널(Null) 문자가 들어간 것을 문자열로 판단하자!

라는 약속이 있습니다.

 

그 널 문자가 바로 '\0' 입니다.

(아스키코드 라는 것을 검색해서 참고하시면 좋습니다. 널 문자를 찾아보세요 ㅎㅎ)

 

제가 작성한 코드 하단부에 array2[4]='\0'; 보이시나요?

이렇게해서 정상적인 출력을 할 수 있습니다.

 

그런데! 앞서 널 문.자. 라고 표현했습니다

네, 널도 문자 입니다.

 

그래서 최초에서는 a,b,c,d,e 5개를 넣었지만 문자열 인식을 위해 'e' 대신 '\0'을 넣은 것 입니다.

 

그러면 모든 배열 끝에 '\0'를 넣어야 하나?

아닙니다. 앞서 말씀드린 것 처럼 문자열일 때 쓰는 것 입니다.

 

따라서 5개의 배열에 문자만 넣어두고 싶다고 하면 처음 초기화한 것 처럼 사용하셔도 됩니다.

 

이처럼 어떤 용도로 어떻게 쓰느냐에 따라 사용방식과 출력방식이 다릅니다.

그래서 실무에서 실수도 많고, 큰 에러도 발생시킨다고 말씀드린 것 입니다.

 

오늘 보여드린 예제는 1차원 배열 입니다.

2차원, 3차원, 다차원 많습니다.

 

차원이 많아지면 그냥 포인터로 사용하기도 합니다.

즉, 메모리 주소로 바로 접근해서 쓴다는 것이죠.

그건 다음 시간에 알아보고요.

 

다차원이라도 꼭 배열로 써야하는 경우도 있습니다.

이는 개발하는 제품이 무엇이냐에 따라 다르고, 우리가 흔히 아는 칩(chip)을 만든 회사가 어떻게 만들어놨느냐에 따라 또 다릅니다.

 

다소 복잡할 수 있겠지만 직접 요리조리 값도 넣어보시고 출력도 해보시면서 결과를 직접 보시기 바랍니다.

 

코딩은 얼마만큼 삽질을 해보았느냐에 따라 실력이 판가름 납니다.

 

열심히 해보시고 스스로의 데이터를 쌓아보십시오!

728x90
반응형

'프로그래밍 > C언어' 카테고리의 다른 글

c언어 - 반복분(for, while)  (0) 2023.07.28
c언어 - 조건문(if, else if, else, switch case)  (0) 2023.07.26
c언어 - 연산자  (0) 2023.07.01
c언어 - 입력받기, 출력하기  (0) 2023.06.29
C언어 - 자료형과 변수  (36) 2023.06.26