|
예전에 어느 사이트에서 빼온 객체와 포인터에 대한 예제입니다.
제가 struct _mankind 구조체에서 Object object;를 빼고 돌렸을 경우.
그래도 동일한 결과가 나오더군요.(전 에러가 나는 줄 알았거든요.)
만일 뺐을경우, creat 함수 부분에서 Object *mankind = (Object *)malloc( sizeof(Mankind) );
에서는 어떻게 처리되는거죠? 할당된 메모리값은 1바이트이고,
그상태에서 다시 object형으로 캐스팅 되었는데 그럼 *mankind는 어떻게 받아들여지는거죠?
여기서 아주 혼란스럽네요. 도움 바랍니다.
--------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h> /* malloc(), free() */
#include <string.h> /* strlen(), strcpy() */
/* 구조체를 타입에 맞게 캐스팅 해주는 매크로 함수 */
#define OBJECT(object) ((Object *)(object))
#define MANKIND(object) ((Mankind *)(object))
typedef struct _object Object;
typedef struct _mankind Mankind;
typedef enum _type Type;
enum _type
{
OBJECT_TYPE, /* 객체(Object) 타입 */
MANKIND_TYPE /* 사람(Mankind) 타입 */
};
struct _object
{
Type type; /* 객체의 종류 */
unsigned long ID; /* 객체의 일련 번호 */
};
struct _mankind
{
Object object; /* 객체(Object) 속성 상속 */
char * name; /* 이름 */
};
/* 객체의 일련번호 부여를 위한 전역 변수 */
unsigned long _objectID = 0;
/*
* 함수의 원형(prototype) 선언
*/
void setObjectID( Object *object );
unsigned long getObjectID( Object *object );
void setObjectType( Object *object, Type type );
Type getObjectType( Object *object );
void freeObject( Object *object );
Object * createMankind(void);
void setMankindName( Mankind *mankind, char *name );
char * getMankindName( Mankind *mankind );
void freeMankind( Mankind *mankind );
/* setObjectID
*
* 객체의 고유 일련번호를 설정한다.
* 이 함수는 사용자가 마음대로 사용할 목적이 아니라,
* 객체가 생성되었을 때 한번 호출해서 객체에게 일련번호를
* 부여하는 것이다.
*
* 전역변수인 _objectID은 객체에게 일련번호를 부여하고 난 후,
* 1씩 증가한다.
*/
void setObjectID( Object *object )
{
object->ID = _objectID++;
}
/* getObjectID
*
* 객체의 고유 일련번호(ID)를 구한다.
*/
unsigned long getObjectID( Object *object )
{
return object->ID;
}
/* setObjectType
*
* 객체의 타입을 설정한다.
*/
void setObjectType( Object *object, Type type )
{
object->type = type;
}
/* getObjectType
*
* 객체의 type을 구한다.
* 객체의 type은 객체의 특성을 말한다.
*
* 객체 생성함수에 따라서 그 객체의 type은 설정된다.
*/
Type getObjectType( Object *object )
{
return object->type;
}
/* freeObject
*
* 생성된 객체의 할당받은 메모리를 해제한다.
* Object의 type을 조사하여 각 type에 맞는 해제 함수를 호출한다.
*/
void freeObject( Object *object )
{
/* 해제시킬 객체의 종류를 알아낸다. */
Type type = getObjectType(object);
/* 종류에 맞는 파괴 함수를 호출 */
switch( type )
{
case OBJECT_TYPE :
break;
case MANKIND_TYPE :
freeMankind( MANKIND(object) ); break;
}
/* 마지막으로 각 type의 크기만큼 할당된 메모리를 해제한다. */
free( object );
}
/* createMankind
*
* 사람 객체를 생성하는 함수이다.
*
* 모든 객체는 create*() 함수로 생성되어지며, 그 객체의 데이터 형은
* Object * 이다.
* 모든 객체의 구조체 타입이 다 다르지만 Object 구조체로 모든 객체를
* 다룰 수 있도록 하기 위해서 메모리는 sizeof(Mankind) 만큼 할당되지만
* 그 할당 받은 메모리를 (Object *)로 캐스팅한다.
*
* 그렇다고 해서 할당받은 메모리의 크기가 변한다던지 하는게 아니라
* 단지 그 할당받은 메모리를 참조하기 위한 index로 Object 구조체를
* 사용하겠다는 것만 알려주는 것일 뿐이다.
*
* 실제로 Mankind 구조체에 있는 속성을 사용하기 위해서,
* (object *)로 캐스팅된 메모리는 다시 (Mankind *)로 캐스팅되야 한다.
* MANKIND(object) 매크로 함수를 사용해도 된다.
*
* 이렇게 캐스팅을 통해서,
* 많은 종류의 객체들을 대표적인 객체 제어 함수로 제어를 할 수 있게 된다.
* 예를 들면 어떤 타입의 객체라도 freeObject() 함수로 파괴를 할 수가
* 있게 되는 것이다.
*/
Object *createMankind(void)
{
/* Mankind 구조체 크기 만큼의 메모리를 할당 받은 후
* (Object *)로 캐스팅 한다.
*/
Object *mankind = (Object *)malloc( sizeof(Mankind) );
if( mankind == NULL ) return NULL;
/* 할당받은 메모리를 0으로 초기화 한다. */
memset( mankind, 0, sizeof(Mankind) );
/* 생성된 객체의 type을 MANKIND_TYPE으로 설정한다.
* 즉, 이 객체는 사람 객체임을 뜻한다.
*/
setObjectType( mankind, MANKIND_TYPE );
/* 생성된 객체의 고유 일련번호를 부여한다. */
setObjectID( mankind );
return mankind;
}
/* setMankindName
*
* 사람 객체의 이름 속성을 설정한다.
*/
void setMankindName( Mankind *mankind, char *name )
{
/* name 인자의 문자열 길이 + 1 만큼 메모리를 할당한다.
* 1을 더하는 이유는 문자열 마지막에 NULL을 저장하기 위함이다.
*/
mankind->name = (char *)malloc( strlen(name) + 1 );
if( mankind->name == NULL ) return;
/* 사람 객체의 이름 속성에 name 을 복사한다. */
strcpy( mankind->name, name );
}
/* getMankindName
*
* 사람 객체의 이름 속성을 구한다.
*/
char *getMankindName( Mankind *mankind )
{
return mankind->name;
}
/* freeMankind
*
* 사람 객체의 속성을 해제하는 파괴함수.
*/
void freeMankind( Mankind *mankind )
{
/* 사람 이름 속성 해제 */
if( mankind->name != NULL )
free( mankind->name );
}
int main(void)
{
Object *man = NULL;
man = createMankind();
setMankindName( MANKIND(man), "Shim sang don" );
printf("Man ID = %ld, name = %s\n",
getObjectID(man), getMankindName( MANKIND(man) ) );
freeObject(man);
return 0;
}
|