일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- Bandit
- C++ 언어 # 핵심 정리
- C언어 # 부록
- MySQL #핵심정리
- Hacking #Baic
- C++ 언어 #핵심정리
- PHP #핵심정리
- C++ 언어 # 핵심정리
- C언어 # 핵심 정리
- shell_script
- HTML #핵심정리
- C언어 #핵심정리
- C언어 #부록
- Today
- Total
cCcode
C Language [핵심정리] - 16 본문
1. 2차원 배열을 포인터에 사용하기
이제 2차원 배열을 포인터에 할당해서 사용해보겠습니다.
이처럼 2차원 배열을 포인터에 바로 할당할 수 있습니다. 다만, 이 때는 자료형과 가로크기가 일치해야 합니다.
+ 3차원 배열
3차원 배열은 높이x가로x세로 형태로 이루어져있습니다.
3차원 배열은 [ ]에 높이, 세로 크기, 가로 크기를 지정하여 선언합니다. 값을 초기화 할 때는 면 단위로 중괄호를 묶어주면 편합니다.
3차원 배열에 접근하려면 [ ]를 세번 사용하여 높이, 세로, 가로 인덱스를 지정해주면 됩니다.
3차원배열을 포인터에 할당하려면 세로x가로로 구성된 면을 가리키는 포인터를 선언하면 됩니다.
여기서 면의 크기가 무엇인지 모르는 분들도 계시겠죠?
3차원 배열은 이와 같은 그림으로 나타낼 수 있습니다. 즉, 면은 하나의 큰 중괄호를 의미하고 있어요.
그리고 각각의 인덱스를 표현하자면 numArr[0]은 높이, numArr[0][0]은 세로, numArr[0][0][0]은 가로입니다.
이처럼 간단한 코드를 통해 각각의 인덱스가 numArr[높이][세로][가로]를 의미한다는 걸 확인할 수 있습니다.
2. 포인터와 배열 응용하기
지금까지는 고정된 크기의 배열을 사용했지만, 이번에는 포인터에 메모리를 할당하여 배열처럼 사용해보겠습니다.
포인터를 배열처럼 사용하는 방법은 간단합니다. 포인터에 malloc 함수로 메모리를 할당하면 됩니다.
이처럼 malloc(sizeof(int) * 10);과 같이 int 크기에 10을 곱하여 동적으로 메모리를 할당합니다. 그리고 배열처럼 [ ] 안에 인덱스를 지정하여 값을 할당하거나 가져올 수 있습니다. 즉, 배열과 메모리가 할당된 포인터는 생성방법만 다를 뿐 값을 다루는 방법은 배열과 동일합니다. 또한, 포인터는 사용한 뒤 free함수로 해제 해준다는 게 다르겠네요.
*numPtr처럼 포인터를 역참조한 것은 numPtr[0]처럼 인덱스로 접근하는 것과 같은 값을 가져옵니다. 그리고 numPtr[1]과 *(numPtr + 1)도 같은 값을 가져오는 데 *(numPtr + 1)와 같이 포인터에 값을 더하는 방식을 포인터 연산이라고 합니다. 제 생각에 numPtr[1]이 *(numPtr + 1)과 같은 값을 가져오는 이유는 numPtr 포인터를 역참조하면 배열의 세로 첫 번째 주소값 즉, 배열이 시작하는 주소([0]번째 인덱스 값의 주소)가 나옵니다. 그래서 인덱스 값이 1인 포인터를 구하려면 해당 인덱스 0에서 1을 더해야 하기 때문에 그렇다고 생각합니다. (이 포인터 연산은 나중에 다시 다루도록 하겠습니다.)
이번에는 사용자가 입력한 크기만큼 메모리를 할당해 배열처럼 사용해보겠습니다.
이번에는 포인터에 메모리를 할당하여 2차원 배열처럼 사용해보겠습니다.
일단 배열의 세로와 가로 순서대로 동적할당을 하며,
처음 세로 공간에 해당하는 메모리를 할당할 때는 세로 공간에 값이 들어가지 않고, 가로공간의 메모리 주소가 들어갑니다. 따라서 sizeof(int)가 아닌 sizeof(int *)처럼 포인터의 크기를 구한 뒤 세로 크기 3을 곱해줍니다. (32bit에선 int나 int*의 크기가 동일해서 상관없지만 64bit에선 int의 크기가 4byte, int *의 크기가 8byte이기 때문에 포인터가 들어갈 공간이라는 걸 확실하게 구분해야 합니다.)
이제 2차원 배열을 사용하듯이 ○포인터 [세로 인덱스][가로 인덱스]를 지정하여 값을 할당하거나 가져옵니다. 그 후에
포인터를 다 사용했다면 먼저 가로 공간에 해당하는 메모리부터 해제합니다. 그리고나서 세로 공간에 해당하는 메모리를 해제합니다. 즉, 할당할 때 세로 → 가로 순서로 할당했으므로, 해제할 때는 반대로 가로 → 세로 순서로 해제합니다.
만약 free(numPtr);처럼 세로 공간에 해당하는 메모리를 먼저 해제해버리면 가로 공간 메모리를 해제할 수 없으므로 주의합니다.
입력한 크기만큼 메모리를 할당하여 포인터를 2차원 배열처럼 사용한 코드를 만들었는데
해당 예제는 다음에 글 시작 부분에 보여드리겠습니다. (warning이 많이 발생해서 수정을 좀 해야할 거 같거든요.)
대신 2차원 배열을 통해 흔히들 아시는 테트리스의 벽 부분을 구현하는 코드를 만들었으니 보여드릴게요.
시간이 별로 없어 완성도가 낮은 점 양해 부탁드립니다.
#include <stdio.h>
#include <string.h>
int main()
{
int block[20][20];
memset(block, 0, sizeof(block));
for (int i = 0; i < sizeof(block) / sizeof(block[0]); i++)
{
for (int j = 0; j < sizeof(block[0]) / sizeof(int); j++)
{
if (i == 0 || i == sizeof(block) / sizeof(block[0]) - 1)
block[i][j] = 1;
else
{
if (j == 0 || j == sizeof(block[0]) / sizeof(int) -1)
block[i][j] = 1;
else
block[i][j] = 8; // 벽 안 쪽에 빈 공간을 숫자로 채우는 부분
}
}
}
for (int i = 0; i < sizeof(block) / sizeof(block[0]); i++)
{
printf(" ");
for (int j = 0; j < sizeof(block[0]) / sizeof(int); j++)
{
if (i == 0 || i == sizeof(block) / sizeof(block[0]) - 1 || j == 0 || j == sizeof(block[0]) / sizeof(int) - 1)
printf("%c ", block[i][j]);
else
printf("%d ", block[i][j]);
}
printf("\n");
}
return 0;
}
△ C언어
우리가 전에 공부했던 배열의 요소 즉, 크기를 구하는 방식을 조건에 사용해서 해당 배열의 선언부 크기만 수정해주시면 결과로 나온 벽 보다 더 크게 구현하실 수 있습니다.
이상입니다.
'C Language Basic' 카테고리의 다른 글
C Language [핵심정리] - 18 (2) | 2021.05.27 |
---|---|
C Language [핵심정리] - 17 (0) | 2021.05.25 |
C Language [핵심정리] - 15 (0) | 2021.05.20 |
C Language [핵심정리] - 14 (0) | 2021.05.19 |
C Language [핵심정리] - 13 (0) | 2021.05.18 |