C언어에 공용체 union이라는 것이 있는데 그렇게 많이 사용되지 않는다.
하지만, 왜 만들었는지 알 필요는 있다. 아래 코드를 보자
#include "STDIO.H"

typedef struct
{   
    void *pfun[8] ;    
} pData ;

typedef    union
{
    struct
    {
        void (*init)(struct _sData *pm, char *pstr) ;     ---(1) void (*init)() ; 으로 정의해도 error가 발생하지 않는다.
        void (*add)(struct _sData *pm, char *pstr) ;
        void (*out)(struct _sData *pm) ;
        void (*add_int)(struct _sData *pm, int num) ;
        int  (*number)(struct _sData *pm) ;
        void (*array)(struct _sData *pm) ;
        int  (*check)(struct _sData *pm, char ch) ;
        void (*sub)(struct _sData *pm, char ch) ;
    };
    pData fun_list ;   
} uFun;

typedef struct _sData
{
    int num ;
    char str[100] ;

    const uFun* const op;
} sData ;


void    init(sData *pm, char *pstr) ;
void    add(sData *pm, char *pstr) ;
void    out(sData *pm) ;
void    add_int(sData *pm, int num) ;
int        number(sData *pm) ;
void    array(sData *pm) ;
int        check(sData *pm, char ch) ;
void    sub(sData *pm, char ch) ;

void main()
{
    const uFun fun_list = { init, add, out, add_int, number, array, check, sub } ;
    sData data = {0, "\0", &fun_list};
    sData obj = {0, "\0", &fun_list};

    char str[100] = "CArA" ;
    int k ;

    printf("[ Data fun ]\n") ;
    data.op->init(&data, str) ;
    data.op->add(&data, "a7A") ;            data.op->out(&data) ;

    k = data.op->number(&data) ;            printf("k : [ %d ]\n", k) ;
    data.op->array(&data) ;                    data.op->out(&data) ;
    data.op->add_int(&data, 7045) ;            data.op->out(&data) ;

    k = data.op->check(&data, 'A') ;        printf("k : [ %d ]\n", k) ;
    data.op->sub(&data, 'A') ;                data.op->out(&data) ;


    printf("\n\n[ Obj fun ]\n") ;   
    obj.op->init(&obj, "Buzzan") ;            obj.op->out(&obj) ;
}

int check(sData *pm, char ch)
{
    int u, d ;
    for(u=0, d=0 ; pm->str[u] !='\0' ;u++)
        if(pm->str[u] == ch)
            d++ ;
    return d ;
}

void sub(sData *pm, char ch)
{
    int u, d ;
    for(u=0, d=0 ; pm->str[u]!='\0' ; u++, d++)
        ((pm->str[u]==ch)?(d--):(pm->str[d]=pm->str[u])) ;
    pm->str[d]='\0' ;
    pm->num=d ;
}

void add_int(sData *pm, int num)
{
    int n = num ;
    while(num>10) {
        int u ;
        for(u=1 ; n>10 ; n=n/10, u = u*10) ;       
        pm->str[pm->num++] = n + '0' ;       
        num = num - n*u ;
        if(!((u/10 < num) && (num < u)))
            pm->str[pm->num++] = '0' ;       
        n = num ;       
    }   
    pm->str[pm->num++] = num + '0';   
    pm->str[pm->num] = '\0' ;
}

int number(sData *pm)
{
    int u, d ;
    for(u=0, d=0 ; unum ; u++)
        if(('0'<=pm->str[u])&&(pm->str[u]<='9'))
            d = d * 10 + (pm->str[u]-'0') ;
    return d ;
}

void array(sData *pm)
{
    char temp ;
    int u ;
    for(u=0 ; unum-1 ; u++) {
        int d ;
        for(d=1 ; dnum-u ; d++)
            if(pm->str[d-1] > pm->str[d]) {
                temp = pm->str[d-1] ;
                pm->str[d-1] = pm->str[d] ;
                pm->str[d] = temp ;
        }
    }
}

void init(sData *pm, char *pstr)
{
    int u ;
    for(u=0 ; pstr[u]!='\0' ; pm->str[u]=pstr[u++]) ;
    pm->str[u]='\0' ;
    pm->num=u ;
}

void add(sData *pm, char *pstr)
{
    int u, n ;
    for(u=0, n=pm->num ; pstr[u]!='\0' ; u++, n++)
        pm->str[n]=pstr[u] ;
    pm->str[n]='\0' ;
    pm->num=n ;
}

void out(sData *pm)
{
    printf("[ Num ] : %d\t[ Str ] : %s\n", pm->num, pm->str) ;
}


프로그램의 결과 보다는 구현방법만 보도록 하자,

union을 사용하지 않는다면 sData의 맴버함수인 uFun의 함수포인터들을 초기화하는 것이 매끄럽지 못하다.
위와 같은 구조는 리눅스 virtual file system 에서 자주 발견된다.

하지만, 이방법을 사용할 때 주의 해야 할 점이 있는데
(1)과 같이 함수의 호출하는 곳과 호출 받는 곳의 prototype이 다를 경우 error나 warning이 발생하지 않는다.
즉, 맴버함수를 정의해 놓은 곳과 구현하는 곳의 prototype이 항상 같은지 눈으로 확인을 해주어야 한다.
만약 매개변수 하나를 더 보내거나 덜 보내 문제가 생길 경우 디버깅하기 까다로운 경우가 발생하기 쉽다.
신고
Write your message and submit
« PREV : 1 : ··· : 23 : 24 : 25 : 26 : 27 : 28 : 29 : 30 : 31 : ··· : 228 : NEXT »