cCcode

C Language [핵심정리] - 16 본문

C Language Basic

C Language [핵심정리] - 16

cCcode 2021. 5. 23. 18:48

1. 2차원 배열을 포인터에 사용하기

이제 2차원 배열을 포인터에 할당해서 사용해보겠습니다.

배열 포인터 - 1
배열 포인터 - 2
결과

이처럼 2차원 배열을 포인터에 바로 할당할 수 있습니다. 다만, 이 때는 자료형가로크기일치해야 합니다. 

 

+ 3차원 배열

3차원 배열은 높이x가로x세로 형태로 이루어져있습니다.

3차원 배열은 [ ]에 높이, 세로 크기, 가로 크기를 지정하여 선언합니다. 값을 초기화 할 때는 면 단위중괄호를 묶어주면 편합니다.

3차원 배열 선언

3차원 배열에 접근하려면 [ ]를 세번 사용하여 높이, 세로, 가로 인덱스를 지정해주면 됩니다.

3차원 배열 접근

3차원배열포인터에 할당하려면 세로x가로로 구성된 을 가리키는 포인터선언하면 됩니다.

포인터에 3차원 배열 할당
3차원 배열의 사용 - 1
3차원 배열의 사용 - 2
결과

여기서 면의 크기가 무엇인지 모르는 분들도 계시겠죠?

3차원 배열

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더해야 하기 때문에 그렇다고 생각합니다. (이 포인터 연산은 나중에 다시 다루도록 하겠습니다.)

 

이번에는 사용자가 입력한 크기만큼 메모리를 할당배열처럼 사용해보겠습니다.

입력 받은 크기만큼 - 1
메모리 할당하여 배열처럼 사용 - 2
결과

 

이번에는 포인터에 메모리를 할당하여 2차원 배열처럼 사용해보겠습니다.

사용 방법
포인터를 2차원 배열처럼 활용 - 1
포인터를 2차원 배열처럼 활용 - 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
Comments