cCcode

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

C Language Basic

C Language [핵심정리] - 12

cCcode 2021. 5. 16. 20:58

1. void 포인터 사용하기

C언어에서는 자료형이 정해지지 않은 void 포인터가 있습니다. void 포인터는 다음과 같이 void 키워드와 *(Asterisk)를 사용해 선언합니다. void * 포인터명;

void 포인터 선언

기본적으로 자료형이 다른 포인터끼리 메모리 주소저장하면 컴파일 경고와 잘못된 값이 나오게 됩니다.

서로 다른 자료형을 가리킬 경우
결과

+ 경고(warning C4133: '초기화 중': 'short *'과(와) 'int *' 사이의 형식이 호환되지 않습니다.) 발생

 

결과를 보면 일단 numPtr에 num의 메모리 주소가 제대로 들어가있습니다. 그러면 자료형이 다르다고 해서 메모리주소가 저장되지 않는건 아닙니다. 그리고 역참조 연산자를 통한 num에서 가져온 값의 출력을 보면 알수없는 값이 있네요. 이런 값이 출력되는 이유는 그전에 설명한것처럼 포인터역참조하면 선언한 자료형의 크기에 맞춰 값을 가져오기 때문에 이 상황에선 short(2byte 크기)에서 int(4byte 크기)만큼의 값을 가져오려고 하니까 당연히 값이 정상적으로 출력될 수 없겠죠.

반대의 경우
결과

반대의 경우에는 문제없이 값이 출력되는 것을 볼 수 있습니다. (다만, 경고는 여전히 존재합니다.)

 

void 포인터는 자료형이 정해지지 않아서  어떤 자료형으로 된 포인터든 모두 저장할 수 있습니다. 반대로 다양한 자료형으로 된 포인터에도 void 포인터를 저장할 수 있습니다. 이런 특성 때문에 void 포인터범용 포인터라고 부릅니다. (직접적으로 자료형을 변환하지 않아도 암시적으로 자료형이 변환되는 방식을 말합니다.) 

void 포인터 사용 - 1
void 포인터 사용 - 2
결과

단, void 포인터자료형이 정해지지 않았으므로 값을 가져오거나 저장할 크기도 정해지지 않았습니다. 그러므로 void 포인터역참조를 할 수 없습니다. 심지어 void 키워드로는 변수를 선언할 수 도 없습니다. 이렇게 들으니까 void 포인터는 정말 쓸모가 없어보이죠..? 그럼에도 void 포인터를 쓰는 이유는 함수에서 다양한 자료형받아들일 때 또는 함수의 반환 포인터다양한 자료형으로 된 포인터에 저장할 때, 자료형을 숨기고 싶을 때 등 다양하게 쓰이고 있습니다.

 

2. 이중 포인터 사용하기

포인터를 선언할 때 *를 두번 사용하면 포인터의 포인터(이중 포인터)를 선언할 수 있습니다.  • 자료형 ** 포인터명; 

 

포인터도 실제로는 변수이기 때문에 메모리 주소를 구할 수 있습니다. 다만, 여기서 중요한 점은 포인터의 메모리 주소는 일반 포인터에 저장할 수는 없고, 이중 포인터저장해야 합니다. 여기서 이중 포인터를 마지막까지 따라가 값을 가져오려면 변수 앞에 역참조 연산자두번 사용하면 됩니다.

이중 포인터

포인터를 선언할 때 *의 개수에 따라 삼중 포인터, 사중 포인터 그 이상도 만들 수 있습니다.

이중 포인터 예시 - 1
이중 포인터 예시 - 2 
결과

+ 잘못된 포인터 사용

포인터는 메모리 주소를 저장하는 용도이므로 다음과 같이 값을 직접적으로 저장하면 안됩니다.

잘못된 포인터 사용

하지만 만약 실제로 존재하는 메모리 주소라면 포인터에 직접 저장할 수 있습니다.

실제 주소 저장

 

3. 메모리 사용하기

이번에 할 것은 포인터에 원하는 만큼 메모리 공간을 할당 받아 사용하는 방법을 알아볼겁니다.

우선 메모리를 사용할 때는 malloc → 사용 → free 패턴으로 사용합니다.

 

1) 메모리를 사용하려면 malloc 함수(memory allocation)로 사용할 메모리 공간을 확보해야 합니다. 이 떄 필요한 메모리 크기byte 단위로 지정합니다. (malloc 함수는 <stdlib.h>파일에 선언되어 있습니다.)

동적 메모리 할당과 해제
결과

위 코드를 보시면 numPtr에는 일반 변수의 메모리 주소를 할당했고, numPtr2에는 malloc함수로 메모리를 할당했습니다. 이 두 할당 방식은 같아 보일지라도 내부적으로는 차이가 있습니다. 그 차이점은 Stack Heap 중 어느 부분에서 메모리를 사용했는가? 입니다. 변수는 stack에서 생성되며 malloc 함수heap의 메모리를 사용합니다.

 

stack과 heap의 가장 큰 차이점은 메모리 해제할 때입니다. stack에서 생성된 변수는 사용한 뒤 별도로 메모리를 해제할 필요가 없지만, malloc 함수를 이용한 경우에는 반드시 별도로 해제 해줘야합니다.

메모리 해제

메모리 해제는 선택이 아닌 필수입니다. 만약 메모리를 할당만하고 해제를 하지 않으면 결국 시스템의 메모리가 부족해져서 운영체제가 프로그램을 강제 종료 시키거나 메모리 할당에 실패하게 됩니다. 특히 메모리를 해제하지 않아 메모리 사용량이 계속 증가하는 현상을 메모리 누수(memory leak)이라고 부릅니다.

 

동적 메모리 할당을 통해 받은 공간을 알아내기 위해서는 sizeof연산자가 아닌 _msize 라는 함수(이 함수는 오직 동적할당된 변수에서만 사용할 수 있습니다.)를 사용합니다.

_msize 함수
결과

왜냐하면 sizeof 연산자자료형의 크기변수의 크기를 구하는 연산자이기 때문에 아무리 메모리를 동적으로 할당을 해도 이 변하지 않습니다. 일단 여러분들이 알아야 할게 있습니다. 변수에 어떤 값을 할당(대입)하기 전까지 그 변수는 아무런 공간을 가지고 있지 않습니다. 변수를 할당(대입)해야 변수가 자신의 크기(ex) int의 경우 4byte)만큼의 공간메모리에서 가져오는 겁니다. 

 

그러니까 여러분들은 sizeof연산자로 구하는 크기를 일종의 가격표라고 생각하면됩니다. 우리는 마트에 가서 그 상품의 가격표를 보고 "이게 얼마구나~"라는 걸 알 수 있죠. 다만, 이 가격표는 실제로 카운터에서 상품을 구입 해야 우리가 지불하는 겁니다. 단지 가격표(크기)를 본다고 돈(메모리 공간)지불(할당)하는 건 아니죠. (이 때 가격표를 보는 행위는 sizeof 연산자를 사용한 출력과 같습니다.)

+ 위에 10줄에서 생긴 경고는 나중에 따로 다루겠습니다.

 

변수 크기만큼 공간이 만들어지는 과정

'C Language Basic' 카테고리의 다른 글

C Language [핵심정리] - 13  (0) 2021.05.18
C Language [핵심정리] - 12 + ∂  (0) 2021.05.17
C Language [핵심정리] - 11  (0) 2021.05.15
C Language [핵심정리] - 10  (0) 2021.05.14
C Language [핵심정리] - 9  (1) 2021.05.14
Comments