C 관련 포스팅 목록
2021.12.07 - [C/응용] - C/C++ 함수 포인터 변수 활용 예제 - 2(구조체 함수 포인터)
2021.12.06 - [C/응용] - C/C++ 함수 포인터 변수 활용 예제 - 1
2021.12.19 - [C/stdio] - C 파일 오프셋 위치 이동 예제 - 2(stdio/fseek/SEEK_END)
2021.12.18 - [C/stdio] - C 파일 오프셋 위치 이동 예제 - 1(stdio/fseek/SEEK_SET)
2021.12.05 - [C/stdio] - C 파일 실시간 쓰기 예제(stdio/fflush)
JAVA 인스턴스처럼 C에서 객체 생성을 따라 하기
안녕하세요.
오늘은 이전 포스팅에서 다뤘던 함수 포인터 활용 예제의 심화 학습으로 마무리 포스팅을 써보도록 하겠습니다. 이전 포스팅에선 구조체 타입을 재정의하여 멤버 변수에 함수 포인터를 사용하는 방법을 알아보았습니다. JAVA에서 클래스를 인스턴스화 하는 것처럼 각각의 객체에 다른 함수 포인터를 전달하여 사용하였습니다.
자바에서는 클래스를 인스턴스화 할 때 가비지 콜렉션에서 알아서 메모리 할당 및 해제를 담당합니다. 따라서 메모리 릭이 발생하지 않도록 관리합니다.
우리가 이전 포스팅에서 사용한 객체 따라하기는 C에서 지역 변수를 할당하여 사용한 것이기 때문에 이미 메모리 공간이 컴파일 단계에서 정해진 이후로 변하지 않습니다. 더군다나 이미 rabbit, dog 변수를 정해서 선언했기 때문에 자바의 클래스 인스턴스화와는 좀 거리가 멉니다.
따라서 오늘은 C의 메모리 관리 API인 malloc과 free를 사용하여 animal이란 타입을 동적 할당하여 자바의 가비지 컬렉션과 같은 역할을 수행할 것입니다.
다만 아주 중요한 것은 자바는 알아서 메모리 관리를 해주지만 C는 절대 그럴 수 없다는 것입니다. 만약 malloc으로 힙 공간에 공간을 동적 할당하였다면 반드시 직접 free를 호출하여 리소스를 해제해주어야 합니다.
그렇지 않을 경우 메모리 릭이 발생하여 시스템에 굉장한 무리를 주게되겠지요.
오늘 예제는 조금 길기 때문에 천천히 따라오시기 바랍니다.
메모리 동적 할당으로 동물 타입 생성 함수 구현
...
...
animal_t *get_animal(const char *name) {
animal_t *animal = NULL;
if (strcmp(name, "rabbit") == 0) {
animal = (animal_t *)malloc(sizeof(animal_t));
animal->cry = cry_rabbit;
} else if (strcmp(name, "dog") == 0) {
animal = (animal_t *)malloc(sizeof(animal_t));
animal->cry = cry_dog;
}
return animal;
}
...
...
라인 설명
3: get_animal 함수를 구현합니다. 이 함수는 인자로 동물 이름을 입력받습니다. 이 이름에 따라 이전 포스팅에서 다뤘던 각자의 cry 함수를 지정합니다. 또한 malloc 함수를 이용하여 animal_t 타입 구조체의 크기만큼 메모리를 힙에 할당하여 포인터를 반환받아 사용합니다.
만약 이전 포스팅 코드를 모르신다면 아래 포스팅을 참고해주세요.
2021.12.07 - [C/응용] - C/C++ 함수 포인터 변수 활용 예제 - 2(구조체 함수 포인터)
전체 코드
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
void (*cry)();
} animal_t;
void cry_rabbit() {
printf("으아악! 난 토끼다\n");
}
void cry_dog() {
printf("어흥!! 난 개다\n");
}
animal_t *get_animal(const char *name) {
animal_t *animal = NULL;
if (strcmp(name, "rabbit") == 0) {
animal = (animal_t *)malloc(sizeof(animal_t));
animal->cry = cry_rabbit;
} else if (strcmp(name, "dog") == 0) {
animal = (animal_t *)malloc(sizeof(animal_t));
animal->cry = cry_dog;
}
return animal;
}
void main() {
animal_t *rabbit, *dog;
rabbit = get_animal("rabbit");
if (!rabbit) {
printf("failed to get rabbit\n");
return;
}
rabbit->cry();
dog = get_animal("dog");
if (!dog) {
printf("failed to get dog\n");
return;
}
dog->cry();
if (rabbit) free(rabbit);
if (dog) free(dog);
}
설명*: get_animal 함수를 통해 반환받은 각 동물 포인터 변수는 힙에 동적 할당된 변수이기 때문에 마지막에 반드시 free 함수에 인자로 전달하여 리소스 해제를 수행해야 합니다.
위의 예제를 실행하면 이전 포스팅과 결과는 같지만 조금 더 객체 지향 언어 스타일로 구현된 것을 알 수 있습니다.
마무리
오늘은 함수 포인터와 구조체, 메모리 동적 할당을 사용하여 조금 더 객체 지향 언어 스타일로 개발하는 방법을 알아보았습니다.
C 관련 포스팅 목록
2021.12.07 - [C/응용] - C/C++ 함수 포인터 변수 활용 예제 - 2(구조체 함수 포인터)
2021.12.06 - [C/응용] - C/C++ 함수 포인터 변수 활용 예제 - 1
2021.12.19 - [C/stdio] - C 파일 오프셋 위치 이동 예제 - 2(stdio/fseek/SEEK_END)
2021.12.18 - [C/stdio] - C 파일 오프셋 위치 이동 예제 - 1(stdio/fseek/SEEK_SET)
2021.12.05 - [C/stdio] - C 파일 실시간 쓰기 예제(stdio/fflush)