일반적인 자료형 할당하기
void 포인터는 자유로운 영혼이다.
void 포인터를 다른 자료형으로 변환하면 역참조를 할 수 있다.
*(할당받은 자료형 *)ptr
역참조란, 포인터형으로 선언된 변수에다가 *를 붙여 값을 얻어낸 과정
#include <stdio.h>
int main()
{
int num1 = 10;
float num2 = 3.5f;
char c1 = 'a';
void *ptr;
ptr = &num1; // num1의 메모리 주소를 void 포인터 ptr에 저장
// printf("%d\n", *ptr); // 컴파일 에러
printf("%d\n", *(int *)ptr); // 10: void 포인터를 int 포인터로 변환한 뒤 역참조
ptr = &num2; // num2의 메모리 주소를 void 포인터 ptr에 저장
// printf("%f\n", *ptr); // 컴파일 에러
printf("%f\n", *(float *)ptr); // 3.500000: void 포인터를 float 포인터로 변환한 뒤 역참조
ptr = &c1; // c1의 메모리 주소를 void 포인터 ptr에 저장
// printf("%c\n", *ptr); // 컴파일 에러
printf("%c\n", *(char *)ptr); // a: void 포인터를 char 포인터로 변환한 뒤 역참조
return 0;
}
구조체 포인터 할당하기
struct에도 마찬가지이다.
할당받은 자료형이 특정 struct로 대체되었을 뿐이다.
(struct Data *)void_ptr
((struct Data *)void_ptr)->member 로 쓴다는 것만 조심하면 된다.
#include <stdio.h>
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
struct Data {
char c1;
int num1;
};
int main()
{
struct Data *d1 = malloc(sizeof(struct Data)); // 포인터에 구조체 크기만큼 메모리 할당
void *ptr; // void 포인터 선언
d1->c1 = 'a';
d1->num1 = 10;
ptr = d1; // void 포인터에 d1 할당. 포인터 자료형이 달라도 컴파일 경고가 발생하지 않음.
((struct Data *)ptr)->num1 = 5;
printf("%c\n", ((struct Data *)ptr)->c1); // 'a' : 구조체 포인터로 변환하여 멤버에 접근
printf("%d\n", ((struct Data *)ptr)->num1); // 5 : 구조체 포인터로 변환하여 멤버에 접근
free(d1); // 동적 메모리 해제
return 0;
}
여기서 printf 할 때를 주목해야 한다.
void 포인터 ptr은 struct Data 포인터를 할당받았다.
void 포인터 ptr로 구조체 포인터 멤버에 접근하고자 한다면 (struct Data *)를 ptr 앞에 명시해주고 다같이 묶은
((struct Data *)ptr)->로 접근해야 한다.
만일 괄호를 빼먹고 (struct Data *)ptr->num1로 사용한다면 동작하지 않는다.
'C언어' 카테고리의 다른 글
[C] 문자열 포인터와 문자열 배열 정리 (0) | 2022.04.19 |
---|---|
[C] 구조체 메모리 크기 계산 빠르게 정리 (0) | 2022.04.18 |