학습 목표
! 본 내용은 검토 전 포스트 입니다. 부정확한 내용이 있을 수 있으니 양해바랍니다.
- 배열의 사용법을 이해한다.
- 인덱스(index)를 이해한다.
- 출력의 원리를 알아본다.
1. 배열
배열은 같은 데이터 형식을 저장한 형태이다. 배열의 사용 방법은 아래와 같다.
1. 데이터 타입 배열명[배열 크기]; // 값이 쓰레기값으로 초기화 됨
2. 데이터 타입 배열명[배열 크기] = {}; // 값이 0으로 초기화 됨
2. 데이터 타입 배열명[배열 크기] = {값1, 값2, ...}; // 값으로 초기화 후 남은 공간은 0으로 초기화 됨
5개의 나이를 저장해야한다고 가정해보자. 여태껏 작성했던 방식으로는 아래처럼 작성할 수 있다. 하지만 이는 코드가 늘어날 뿐만 아니라 5개의 변수를 출력하기 위해서 모든 변수를 불러야한다.
#include <stdio.h>
int main(void) {
int age1 = 23, age2 = 13, age3 = 17, age4 = 15, age5 = 11;
printf("age1 = %d\n", age1); // age1 = 23
printf("age2 = %d\n", age2); // age2 = 13
printf("age3 = %d\n", age3); // age3 = 17
printf("age4 = %d\n", age4); // age4 = 15
printf("age5 = %d\n", age5); // age5 = 11
}
5개의 나이는 데이터 형식이 모두 정수로 배열형식으로 작성할 수 있다. 아래 코드는 위 코드를 배열 형식으로 작성한 코드이다. 배열을 초기화 한 후 배열명[숫자]로 값을 출력할 수 있다.
#include <stdio.h>
int main(void) {
int age[5] = {23, 13, 17, 15, 11};
printf("age1 = %d\n", age[0]); // age1 = 23
printf("age2 = %d\n", age[1]); // age2 = 13
printf("age3 = %d\n", age[2]); // age3 = 17
printf("age4 = %d\n", age[3]); // age4 = 15
printf("age5 = %d\n", age[4]); // age5 = 11
}
2. 인덱스
아래 코드에서 첫번째 값인 23을 출력하기 위해서 age[1]이 아닌 age[0]이 출력 되었을까? 이는 인덱스와 관련 있다. 인덱스는 기준점으로부터 찾고자 하는 데이터까지의 떨어진 거리를 의미한다.
#include <stdio.h>
int main(void) {
int age[5] = {23, 13, 17, 15, 11};
printf("age1 = %d\n", age[0]); // age1 = 23
printf("age2 = %d\n", age[1]); // age2 = 13
printf("age3 = %d\n", age[2]); // age3 = 17
printf("age4 = %d\n", age[3]); // age4 = 15
printf("age5 = %d\n", age[4]); // age5 = 11
}
아래 표를 참고하여 인덱스를 이해해보겠다. 기준점은 값의 시작 부분에 위치한다. 따라서 age[0]은 기준점으로부터 0만큼 떨어져있는 23을 출력하게 된다. 따라서 배열명[숫자]의 정확한 표현은 배열명[인덱스]이다.
기준점 | |||||
---|---|---|---|---|---|
값 | 23 | 13 | 17 | 15 | 11 |
기준점으로 부터 떨어진 거리 | 0 | 1 | 2 | 3 | 4 |
따라서 값을 출력하기 위해서 아래와 같은 반복문을 사용할 수 있다.
#include <stdio.h>
int main(void) {
int age[5] = {23, 13, 17, 15, 11};
for(int i = 0 ; i < 5 ; i++) {
printf("age[%d] = %d\n", i, age[i]);
}
}
3. 2차원 배열
추상적인 모형으로 생각했을 때 1차원 배열이 일렬로 되어있는 형태를 띈다면 2차원 배열은 면의 형태를 띈다. 2차원 배열의 형식은 아래와 같다. 1차원 배열 여러개를 중괄호를 묶은 형태이다.
1. 데이터 타입 배열명[세로 크기][가로 크기]; // 값이 쓰레기값으로 초기화 됨
2. 데이터 타입 배열명[세로 크기][가로 크기] = {}; // 값이 0으로 초기화 됨
3. 데이터 타입 배열명[세로 크기][가로 크기] = {{값1, 값2, ...},
값3, 값4, 값5},
... }}; // 값으로 초기화 후 남은 공간은 0으로 초기화 됨
2차원 배열은 첫번째 대괄호가 세로이고 두번째 대괄호가 가로이다.
#include <stdio.h>
int main(void) {
int arr[2][2] = {{1, 2},
{3, 4}};
printf("arr[0][0] = %d\n", arr[0][0]);
printf("arr[0][1] = %d\n", arr[0][1]);
printf("arr[1][0] = %d\n", arr[1][0]);
printf("arr[1][1] = %d\n", arr[1][1]);
return 0;
}
2차원 배열을 반복문 등에서 다룰때는 h(height), w(weight) 약자를 많이 사용한다.
#include <stdio.h>
int main(void) {
int arr[2][2] = {{1, 2},
{3, 4}};
for(int h = 0 ; h < 2 ; h++) {
for(int w = 0 ; w < 2 ; w++) {
printf("arr[%d][%d] = %d\n", h, w, arr[h][w]);
}
}
return 0;
}
4. 문자열 출력
아래는 str 변수에 문자열 ‘Hello world’을 저장하고 문자열을 출력하는 코드이다. 문자열의 경우 배열의 크기를 비워놓으면 문자열의 크기에 맞게 배열의 크기가 할당되게 된다. “Hello world”는 띄어쓰기 포함 11글자인데 12글자로 나온다. 이유는 아래 설명하겠다.
#include <stdio.h>
int main(void) {
char str[] = "Hello world";
printf("sizeof(str) = %d", sizeof(str)); // sizeof(str) = 12
}
아래 코드는 각 단어와 아스키코드를 출력한다. 이를 표로 나타내면 아래 표와 같다. 특이한 점은 맨 뒤에 자동으로 NULL이 붙는다는 것이다. NULL은 ‘존재하지 않는 값’으로 따로 출력하거나 할 수 있는 값은 아니지만 NULL은 특별한 기능을 한다. 문자열에서의 NULL은 문자열이 끝남을 의미한다.
#include <stdio.h>
int main(void) {
char str[] = "Hello world";
for(int i = 0 ; i < sizeof(str) ; i++) {
printf("%c 0x%x\n", str[i], str[i]);
}
return 0;
}
기준점 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
값 | H | e | l | l | o | Space | w | o | r | l | d | NULL |
아스키코드 | 0x68 | 0x65 | 0x6c | 0x6c | 0x6f | 0x20 | 0x77 | 0x6f | 0x72 | 0x6c | 0x64 | 0x00 |
기준점으로 부터 떨어진 거리 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
아래는 11번째 인덱스의 NULL을 강제로 ‘A’로 대치한 후 출력이다. 컴파일 환경에 따라 다르지만 기존 문자열 ‘Hello world’ 다음에 알 수 없는 값이 출력된다. 해당 값은 기존 문자열 뒤 쓰레기 값이 출력된것이고 우연히 NULL을 만날때까지 계속 출력된다. 이를 악용하여 문자열 뒤에 NULL을 없애 쓰레기 값이나 다른 변수 값을 읽을 수도 있다.
#include <stdio.h>
int main(void) {
char str[12] = "Hello world";
str[11] = "A";
printf("%s", str); // Hello world�
}
'초보 해커를 위한 C언어와 동작 원리 > Ch2. Programming' 카테고리의 다른 글
배열과 포인터 (2) | 2025.04.22 |
---|---|
포인터 (0) | 2025.04.22 |
난수 (0) | 2025.04.22 |
디버깅 (0) | 2025.04.22 |
반복문 (0) | 2025.04.22 |