배열부터가 조금 신경써서 봐야할 내용입니다.
앞서 진행한 내용들은 입문에서 다소 가볍게 보셔도 되는 내용입니다.
앞으로 진행할 배열과 포인터는 중요하다고 볼 수 있는데요.
이유는 배열, 포인터 사용에 메모리 사용법이 필수이고, 그에 따라 메모리 주소가 어떻고 저떻고 나오기도 하고
실무에서 실수하면 각 종 버그는 물론이고, 알 수 없는 이유로 프로그램이 죽는 이유가 생기기 때문입니다.
현재 입문을 기준으로 설명드리기에 실무에까지 적용될 내용은 진행되지 않겠지만
개념과 사용법은 꼭 알아두시는 것이 좋습니다.
배열
사전적 의미로는 "일정한 차례나 간격에 따라 벌여 놓음." 이라는 뜻 입니다.
컴퓨터 용어에서의 배열을 다시 얘기해 본다면 "번호와 번호에 대응하는 데이터들로 이루어진 자료구조" 라고 할 수 있겠습니다.
번호라는 용어는 잘 안쓰이고 인덱스(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)을 만든 회사가 어떻게 만들어놨느냐에 따라 또 다릅니다.
다소 복잡할 수 있겠지만 직접 요리조리 값도 넣어보시고 출력도 해보시면서 결과를 직접 보시기 바랍니다.
코딩은 얼마만큼 삽질을 해보았느냐에 따라 실력이 판가름 납니다.
열심히 해보시고 스스로의 데이터를 쌓아보십시오!
'프로그래밍 > 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 |