C++ (15) - 구조체 포인터와 동적할당
본 내용은 어소트락 무료 강의 <C/C++ 무료강의>을 기반으로 공부한 내용을 정리한 것이다. 틀린 내용이 있을 수도 있음.
구조체 포인터
구조체 = 내가 직접만드는 자료형!!
typedef struct _tagMyST { int a; 구조체 내부 ‘멤버’ -> 변수가 아니다! float f; }MYST;
MYST s = {};
s.a;
MYST s2; MYST s3;
s2.a; s3.a;
구조체를 만들었으면 이런 포인터도 가능하지 않을까?
MYST* pST = &s; pST + 1; -> 8바이트 단위로 주소 변경!!
*pST; 변수 s를 가리키고 그곳이 int 파트와 float파트로 나뉘어 있음.
(pST).a = 100; -> a파트(int)에 100이 들어간다. (pST).f = 3.14f; -> f파트(float)에 3.14가 들어간다.
실제 공간과는 어떤 상관도 없이 값이 들어간다. 포인터 타입과 실제 타입을 맞춰줘야함.
저 역참조 표현이 너무 귀찮아서 이렇게 표현한다.
pST -> a; pST에 가서 a pST -> f; pST에 가서 f
동적할당 (1)
#include
// 메모리 영역 // 힙 영역(동적할당)
int main() { malloc();
return 0; }
malloc(); 함수?? 런타임 중 대응할수 있는 기능이 가능한 메모리 영역이 필요. 이를 동적할당이라 한다. 변수는 코드로 이미 만들어 놓은것이고, 런타임 중 수정이 불가능하다. 그래서 어떠한 변수들도 힙 영역을 사용할 수 없음.
힙 영역을 변수 없이 사용할 수 있는 이유가 바로 포인터이다.
malloc 내가 지정한 사이즈 만큼 힙 영역에 메모리 생성. malloc(100); 100 바이트가 힙 영역에 생성 후 주소를 준다. int* pInt = (int*)malloc(100); 100바이트를 할당한 시작 주소값을 int 포인터 변수에 넣어 준 것.
반환타입이 void 포인터!! -> 주소는 주소인데 원형 타입을 정하지 않아 반환타입이 없어.
왜 void포인터로 반환할까? float* pF = (float*)malloc(4); *pF = 1.23f;
malloc을 통해 힙 영역에 바이트를 주고, 그 바이트를 어떤 자료형으로 사용할지는 사용자가 정의한다. 따라서 void 포인터를 반환해서 원하는 자료형으로 사용할 수 있어야하기 때문에 void 포인터로 반환한다. void 포인터로 반환되지 않는다면 해당 바이트를 고정된 자료형만 사용해야한다.
malloc은 순수하게 바이트에 맞는 공간을 생성하고 어떤 자료형이라고 알려주지 않고서 주소 시작값만을 전달한다.
동적할당 (2)
float* pF = (float)malloc(4); int pI = (int*)pF; 둘다 같은 힙 영역을 가리킨다.
이상태에서
*pF = 2.4f;
2.4를 넣으면 실수값으로 들어간다.
근데 그 값을 int 포인터로 값을 읽어오면..
int i = *pI;
int 포인터로 실수값을 읽어버리니까 부동소수점에의해 이상한 값으로 읽어온다.
동적할당은 할당된 힙 영역 바이트를 어떤 자료형으로 쓸 지 사용자에 의해 정해져서 사용되는 기능
동적할당에서 중요한 점
-
런타임 중에 대응이 가능
-
프로그램 실행 도중 메모리를 잡는다면 해제는 ? -> 사용자가 직접 관리해야함 메모리가 누수가 나는지를 확인해야한다!
int iInput = 0; scanf_s(“%d”, &iInput);
int* pInt = nullptr;
if (100 == iInput) { pInt = (int*)malloc(100); }
if (nullptr != pInt) { free(pInt); 힙 영역 메모리 해제 함수 free } return 0;
이런게 해제가 잘 안되어서 메모리 해제가 안된다면 메모리 누수로 오류발생
가비지컬렉터 : 가상머신에서 알아서 메모리를 관리해줌.