1차원 배열과 초기화
아래의 프로그램을 보면
배열명을 사용하기 전에 이 배열이 어떠한 값을 저장할 수 있는지를 지정하는 타입이 있고,
배열의 첨자를 이용하여 배열의 개수를 지정한다는 것을 알 수 있습니다.
C 에서 배열의 첨자는 반드시 0 부터 시작합니다.
그러므로 정의할 때의 첨자 수와 사용할때의 첨자는 -1의 오차를 보이게 됩니다.
즉 아래 프로그램에서 mozi[2] 는 사용해서는 안됩니다.
main() { int mozi[2]; printf("%d %d\n", mozi[0], mozi[1]); }
배열의 초기화
위의 프로그램에서 배열은 초기화를 하지 않았습니다.
초기화를 하지 않았기 때문에 어떠한 값이 들어가 있는지 아무도 모르며, 아무값이나 출력됩니다.
아무값이나 출력되지 않게 하기 위해서는 초기화를 해줘야 합니다.
main()
{
int mozi[2];
mozi[0] = 0;
printf("%d %d\n", mozi[0], mozi[1]);
}
이 프로그램은 mozi[0] 에 대해서만 초기화를 하였기 때문에, mozi[1] 에 대해서는 여전히 쓰레기 값이 들어가있습니다.
배열 전체를 초기화 하기위해서는 아래처럼 해주어야 합니다.
초기화 방법 1은 너무 무식한 방법이므로, 초기화 방법 2나 3을 사용하도록 합니다.
초기화 방법 1 mozi[0] = 0; mozi[1] = 0; 초기화 방법 2 for(i = 0; i < 2; i++) mozi[i] = 0; 초기화 방법 3 int mozi[3] = {0};
첨자 생략
배열의 초기값을 다음과 같이 설정했다고 가정합니다.
int mozi[2] = {4, 3, 7};
배열의 첨자는 2 로 지정하고, 초기치의 개수는 3 개 입니다.
이 정의는 경고를 발생시키지만 에러로 처리시키지는 않습니다.
컴파일 하고 실행하면 mozi[0] 은 4 mozi[1] 은 3 으로 잘 출력됩니다.
그러나 mozi[2] 에 대해서는 컴파일러가 메모리 할당을 하지 않기 때문에 7 이라는 값이 출력되지 않습니다.
이러한 실수를 방지하는 방법은 배열선언시 첨자의 길이를 생략하는 것입니다.
int mozi[] = {4, 3, 7};
위 처럼 작성하는 경우 컴파일러는 초기치의 개수를 세고나서 이를 첨자에 반영합니다.
따라서 mozi 의 첨자는 자동으로 3 이 되고 메모리는 12 바이트가 할당될 것 입니다.
다차원 배열
다차원 배열은 배열의 배열로 생각하면 쉽습니다.
int mozi[2][3]; printf("%d %d %d %d %d %d\n", mozi[0][0], mozi[0][1], mozi[0][2], mozi[1][0], mozi[1][1], mozi[1][2]);
마찬가지로 모두 쓰레기 값이 출력됩니다.
1차원 배열을 초기화 했듯이, 2차원 배열도 초기화를 해줍니다.
int mozi[2][3] = {0};
만약 0으로 초기화 하지 않고 다른 값으로 초기화 하고 싶은 경우 아래처럼 진행합니다.
int mozi[2][3] = { {1, 2, 3}, {4, 5, 6} };
1차원 배열과 포인터
그렇다면 배열을 포인터와 어떻게 결합할 건지 보기로 해봅니다.
main() { int mozi[2] = {1, 2}; int *tistory; tistory = mozi; printf("%d\n", *tistory); }
소스를 보면 tistory는 mozi 변수에 대해 & 기호를 사용하지 않고 바로 사용했습니다. 왜그럴까요?
배열명은 배열의 첫번째 배열 요소의 주소를 뜻합니다.
mozi[0], mozi[1] 배열 요소들은 메모리의 어딘가에 할당되어 있을 것이고, &mozi[0], &mozi[1] 로 알 수 있습니다.
그런데 배열명은 배열의 첫번째 배열 주소를 가지고 있다고 했으므로, 다음의 식이 성립합니다.
mozi == &mozi[0]
결국 mozi 라는 배열명 자체가 주소 값을 뜻하기 때문에 이 주소 값을 tistory 라는 포인터 변수에 넣을 수 있는 겁니다.
같은의미이지만 달리말하면 tistory 는 mozi[0] 을 가리키고 있다고 할 수 있습니다.
그렇다면 mozi[1] 을 얻기위해선 어떻게 해야할까?
포인터 + 정수의 의미
아래의 프로그램의 tistory + 1 을 봅니다. 이 수식은 어떤걸 의미할까요?
tistory 가 정수형 변수라면 "정수 + 1" 이 되겠지만, 포인터 변수이므로 주소가 들어가 있으며 이 주소에 1을 더한다는 의미입니다.
int mozi[2] = {0, 1}; int *tistory; tistory = mozi; tistory + 1;
여기에서 1을 더한다는 의미는
tistory 의 주소가 0x22334455 인 경우 +1 증가한 0x22334456 가 아닙니다.
tistory 의 주소에 포인터 변수의 타입 크기만큼 증가한다는 것 입니다. 정수형 변수의 크기는 4 byte 이므로 0x22334459 가 됩니다.
mozi[0] = 0; // 0x8047dlc mozi[1] = 1; // 0x8047d20 tistory + 0; // 0x8047dlc tistory + 1; // 0x8047d20
그렇다면 정수를 더할 때 괄호의 중요성를 알아보도록 합니다.
int mozi[2] = {0, 3}; int *tistory; tistory = mozi; printf("%d %d\n", *(tistory + 1), *tistory + 1);
결과는 어떻게 출력될까요? 괄호 없이 계산시 * 연산자는 + 보다 순위가 높습니다.
따라서, *(tistory + 1) 은 mozi 시작주소에서 4 byte 를 더한 주소에 있는 값을 출력하므로 3 이라는 값이 출력됩니다.
*tistory + 1 은 mozi 의 시작주소에 있는 값을 가지고 온 후에 1 을 더하므로 1 이라는 값이 출력됩니다.
'Computer Language > C' 카테고리의 다른 글
[C] 문자열과 포인터 사용법 알아보기 (0) | 2018.11.20 |
---|---|
[C] 2차원 배열과 포인터 학습하기 (0) | 2018.11.18 |
[C] 포인터란 무엇인가? (0) | 2018.11.16 |
[C] 스택 개념, 함수, 코드 정리 (0) | 2018.11.08 |
[C] 큐 개념, 종류 및 작동 방식, 코드 정리 (0) | 2018.11.08 |