- 배열(Array)
- 상수(Constant)
- Q&A
- 마치며
우리가 프로그램을 짜다보면 여러 변수를 활용해야 할 때도 있습니다.
예를 들어 int형 변수 10개가 필요할 때처럼 말이죠.
그럼 우리는 하나씩 일일이 작성해야할까요?
물론, 그래도 되지만 여러 문제점이 있겠죠.
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
매 변수 이름을 위처럼 나열하면 복잡합니다.
해당 변수들을 활용하기도 복잡합니다.
(위의 변수들을 모두 더하려면 a1 + a2 + a3 + ... + a10
이렇게 해야죠...어우..)
따라서 C에서는 컴퓨터 메모리 상에서, 같은 타입의 변수들을 연속적으로 여러 개를 한 꺼번에 정의할 수 있는 '배열(Array)'를 제공합니다.
- 배열 (Array)
: 같은 타입의 변수들을 연속적으로 여러 개를 한 꺼번에 정의할 수 있는 집합
: 특정한 형(Type)의 변수들의 집합
- 변수의 선언
(변수 Type) (변수 이름) = (값)
- 배열(Array)의 선언
(변수 Type) (배열 이름)[원소 개수] = {값}
#include <stdio.h>
int main() {
int a = 1;
int arr[3] = {1, 2, 3};
return 0;
}
배열을 다룰 때는 몇 가지 주의점이 있습니다.
{ }
을 이용한 선언배열의 선언 시에는 { }
를 이용하여 배열의 원소들을 초기화할 수 있습니다.
하지만 이미 정의된 배열에는 { }
을 이용하여 사용할 수 없습니다.
#include <stdio.h>
int main() {
int arr[3] = { 1, 2, 3 };
arr = { 4, 5, 6 }; // Compile Error!!!
return 0;
}
를 실행해보면 컴파일 오류가 발생합니다.
배열 선언 시에 [ ]
사이에 원소 크기를 넣어서 초기화했습니다.
그런데, { }
를 이용해 배열을 정의했다면, 배열의 크기를 생략해도 컴파일러가 알아서 배열을 정의해줍니다.
'
#include <stdio.h>
int main() {
int arr1[3] = { 1, 2, 3 };
int arr2[] = { 1,2,3 };
return 0;
}
위의 arr1
은 배열 크기를 명시적으로 작성했지만,
arr2
는 배열 크기를 생략했습니다.
그래도 오류없이 잘 실행됩니다 😊
단, 배열 크기를 명시적으로 작성할 떄는 반드시 '값'이 들어가야 합니다.
변수는 들어가면 오류가 발생합니다.
왜냐하면, 처음에 컴파일러가 배열을 처리할 때 메모리 상에 공간을 잡아야 하는데, 이 때 공간의 크기는 반드시 값으로 주어져야 합니다!
배열의 크기는 임의로 정해지지 않습니다.
즉, 컴파일러는 우리가 어떠한 크기의 배열을 정의하고자 하는지 모릅니다.
우리가 변수를 사용할 때, 해당 변수가 초기화되지 않았다면 컴퓨터는 접근 자체를 허용하지 않습니다.
#include <stdio.h>
int main() {
int a;
printf("%d", a);
return 0;
}
위의 예시에서 변수 a
는 초기화되지 않았고,
실행해보면 오류가 발생합니다.
더욱이, 배열도 마찬가지죠.
#include <stdio.h>
int main() {
int arr[3];
arr[0] = 1;
printf("%d", arr[1]);
return 0;
}
위의 예시에서는, 초기화 되지 않은 배열 arr[1]
을 값에 접근합니다. 당연히 오류가 발생하죠.
그렇다면 다음 예시는 어떨까요?
#include <stdio.h>
int main() {
int arr[3] = {1};
printf("%d", arr[1]);
return 0;
}
[Result]
0
???????????????????
정상적으로 실행이 됩니다.
즉, 위의 예시에서는
int arr[3];
arr[0] = 1
처럼 수행됐습니다.
그런데 아까 예제에서는 오류가 발생했죠.
즉, 컴퓨터는 위의 int arr[3] = {1};
라는 문장을
int arr[3] = {1, 0, 0};
처럼 해석해서 작동했습니다.
따라서, 자동적으로 우리가 초기화하지 않은 원소들에게는 0
이 들어가게 됩니다.
C에서 배열의 n번째 원소에 접근할 때는 arr[n-1]
와 같이 작성하면 됩니다.
- 배열에서의 n번째 원소 접근
(배열 이름)[n-1]
#include <stdio.h>
int main() {
int arr[3] = { 1, 2, 3 };
printf("%d", arr[1]);
return 0;
}
[Result]
2
위의 예시에서 arr[3]
을 출력해볼까요?
실제로 출력해보면 이상한 값이 나옵니다 🤔
왜 그런걸까요??
C에서 배열은 해당 타입의 변수들의 나열이라고 생각하면 됩니다.
즉, 배열에는 배열에 크기에 관한 그 어떠한 정보가 없습니다.
arr[1]
이라고 한다면 컴퓨터는 '배열의 처음 위치에서부터 2번째 원소구나!'라고만 생각합니다.
그렇다면 arr
배열의 끝 부분을 봅시다.
메모리 상에서는 arr[2]
의 뒤에는 다른 변수들의 데이터가 있을 것입니다.
즉, 컴퓨터는 arr[2]
뒤에 arr[3]
이 있는 것처럼 생각해 그 값을 보여주게 됩니다.
만약, 해당 위치가 접근 불가능하다면, 오류를 출력할 것입니다.
최악은, 해당 부분의 값을 다른 값으로 덮어씌울 경우입니다.
이는 정말 찾기 어려운 버그로 이어질 가능성이 높습니다!!
만약 해당 영역을 변수 b
라는 놈이 있다고 해봅시다.
그 때, arr[3] = 7
을 한다면 변수 b = 7
을 하게 된 것과 마찬가지입니다.
따라서, 배열을 사용할 때는,
우리가 참조하는 원소의 위치가 배열의 크기 보다 작은지 꼭 확인해야 합니다.
C에서는, 배열의 원소를 또 다른 배열로 하는 다차원 배열을 만들 수 있습니다.
2차원 배열
(배열 Type) (배열 이름)[배열 크기][배열 크기]
int arr[3][2];
는 다음처럼 생각하면 됩니다.
또한, 다차원 배열을 정의할 때는, 맨 앞 크기를 제외한 나머지 크기들을 정확히 지정해줘야 오류가 발생하지 않습니다.
즉,
int arr1[][3] = {...}
int arr2[3][] = {...}
에서 arr1
은 정상적으로 컴파일 되지만, arr2
는 오류가 발생합니다.
상수는 변수와 반대로 처음 정의할 때 그 값이 바로 주어지고, 영원히 바뀌지 않습니다.
- 상수(Constant)
const (상수 Type)(상수 이름) = (상수의 값)
#include <stdio.h>
int main() {
const int a = 5; // Constant
printf("%d", a);
return 0;
}
처음 상수를 정의할 때 반드시 값을 정의해야 합니다. 만약 하지 않는다면 오류가 발생합니다.
어떻게 해도 바꿀 수 없다는 상수의 특성 때문에,
배열의 크기로 상수를 사용할 수 있을까 생각할 수 있는데요,
#include <stdio.h>
int main() {
int b = 3;
const int a = b;
char c[a];
return 0;
}
위의 예시처럼, 상수 a
로 배열 크기를 할당한다고 하면 변수 b
의 크기로 배열의 크기를 지정할 수 있다는 말이 되므로, '변수로 배열의 크기를 지정할 수 없다'라는 말에 반하게 됩니다.
따라서, 상수로 배열 크기를 할당할 수 없습니다😢
-
드디어 배열(Array)에 대해 배웠습니다.
배열은 정말 많이 쓰이죠..
작은 프로그램부터 큰 프로그램까지 범용적으로 쓰이게 되는데요,
사실 C에서 배열을 다룰 때 워낙 까다로워서 많이 헤매던 기억이 송송 떠오르네요...😂
(사실 🐶고생이었죠...)
이제는 활용하는데 무리가 없을 정도로 잘 기억&연습해서 꼭 마스터 해야겠습니다!!!!!!
[Reference] : 위 글은 다음 내용을 참고, 인용하여 만들어졌습니다.