함수포인터 C언어 시절에는 굉장히 중요한 문법이었지만. C++로 넘어가면서 그 중요도가 많이 줄어들었음.
함수 포인터 : 함수의 주소를 저장하는 용도의 포인터 함수의 이름이 곧 함수가 저장되어 있는 메모리 공간의 주소다. 그것을 저장하는 것이 함수 포인터.
반환타입(*포인터 변수이름)(매개변수 형식)
void (* pFuc)() = Render;
void Render(){
cout << "HelloWorld";
}
pFunc();
함수 포인터는 함수의 이름만 알고 있다면 여러 함수를 필요에 따라 변경해가면서 사용할 수 있음.
그러나, C++을 들어가면서 캡슐화 / 은닉화 라는 개념이 들어가게 되며 주소만 알고 있다면 모두가 접근할 수 있던 이전의 방식과 코드 철학이 맞지 않게 되어가면서 점차 사용성이 줄어들게 되었음.
int Add(int Dst, int Src);
int(*pClac)(int, int) = Add;
int Add(int Dst, int Src){
return Dst + Src;
}
pCalc(5,5);
함수 포인터는 배열로 선언하여 여러 함수를 저장하는 용도로 사용하는 것이 일반적임.
사용자 정의 타입 2.
현 시점에서는 자주 사용하지 않고 있음.
union uniInfo
{
int iKor;
double fAver;
}
유니온은 초기화하고자 할 때, 구조체와 달리 각 멤버 변수를 초기화해주는 것이 아니다. 멤버 변수 중, 가장 큰 자료형의 크기만큼 메모리가 할당되고, 모든 멤버 변수가 그 메모리를 공유하여 사용한다.
즉, 위에 따지면 double 8바이트만 할당이 된다. 그렇기에 멤버 변수들의 주소는 같다
그렇기에 다른 형태의 자료형끼리는 비트 표현 방식이 다르기에 오해가 생길 수 있다. 바이트 수를 초과할 때 이어붙여서 만드는 것에는 사용이 가능함. (8바이트 4개를 구조체로 넣고 유니온의 멤버변수로 넣으면 32바이트가 가능해진다.)
정말 메모리가 부족할 때 사용하는 문법 (ex 임베디드드)
열거체 열거체 : 상수를 한번에 여러개 만들기 위한 문법. 멤버라는 개념이 없음. 그렇기에 멤버 접근 연산자 (.) 을 사용할 수 없고 마찬가지로 (→) 연산자 불가.
enum NUMBER{
ONE = 1,
TWO,
THREE,
FOUR,
END
}
int main(){
NUMBER eNumber = ONE;
}
자료형의 크기는 무조건 4바이트로 고정되어 있음. 여러 상수를 사용할 때에는 매우 효율적임.
(실제 사용시에는 초기화해서 사용하지 않고, 안에 선언한 상수를 사용함)
cout << ONE << endl;
<상식>
int iData = ONE + TWO;
이 코드는 원래 자료형이 다르기에 안되는 것이 맞지만, 컴파일러 상에서 상수로 변환하여 계산을 해주는 것임.
동적할당
정적 : 프로그램 시작하기 이전에
동적 : 프로그램이 구동하고 있는 중.
프로그램이 구동 중일 때 메모리 사용 허가를 받겠다! 하는 것이 동적 할당임.
힙 영역 메모리 : 프로그램 구동 중에 동적할당이 가능함!
C언어 동적 할당 문법 반드시! 포인터가 필요하다!
int main(){
// malloc, calloc
int * p = malloc(4); X
int * p = (int*)malloc(4); O - 반드시 명시적 형변환
*p = 100;
cout << (*p) << endl;
int * p = (int*)malloc(sizeof(int) * 4); O - 반드시 명시적 형변환
}
malloc은 void* (보이드 포인터형)을 반환하는 함수, void * 는 어떤 타입의 주소인지 모르는 경우 사용함. void * 을 사용할 때 어떤 자료형의 주소 형식인지 ‘반드시’ 명시적 형변환을 해야함.
malloc은 할당한 heap영역의 첫번째 주소를 반환함. 힙 영역의 주소는 변수로 호출할 수 없기에, 반드시 포인터를 쓰는 것임.
int* p = (int*)malloc(16);
for(int i=0; i < 4; ++i){
p[i] = i+1;
} //동적 배열과 유사
int* pArray = (int*)calloc(4, sizeof(int));
동적 배열을 만들 때 굉장히 편해지는 것. calloc을 하게 되면 할당받은 heap공간의 배열이 자동으로 0 초기화가 됨.
메모리 반환
void free(void * ptr)
int* p = (int*)malloc(4);
free(p);
heap영역의 ‘사용권한’을 반납하는 함수. (p가 가리키는 주소는 같음. 심지어 free하고도 주소로 접근하여 읽고 쓰기 가능함.) 즉, 댕글링 포인터 출현 ( : 주소의 사용 권한이 없음에도 포인터여서 사용의 문제를 야기할 수 있는 포인터.)
p = null;
그렇기에 주소를 반드시 null로 변환을 해주어야 함.