union (共用体)を使う


もうひとつは、共用体。これは、struct と似た形をしてますが、 全然違うものです。
    struct A { int A0; double A1; int * A2; };
は、A0,A1,A2全てを要素にもつデータ構造です。 一方で、
    union B { int B0; double B1; int * B2; };
は、B0,B1,B2いずれかを要素にもつデータ構造です。 例えば、あるデータ構造は、中身が int, double, int* のどれかなんだけど、という時に使います。 tag と言われる中身の種類を表すための札(フダ)と一緒に使われることが多いです (ソース) 。
/* もう一度 enum 登場 */
typedef enum { tagInt, tagDouble, tagSymbol, tagComposite } tagSData_t;

typedef struct SData { /* この SData は、 */
    tagSData_t tag;    /* 中身の種類を tag で表し */
    union {
	int valInt;       /* valInt や、、、のいずれかを */
	double valDouble;
	char * valSymbol;
	SDataList_tp valComposite;
    } body;               /* body のなかに格納している。*/
} SData_t, * SData_tp;

/*
 * pretty print という中身を綺麗に表示する関数をつくります
 */ 
void pprintrint_SDataInt(SData_tp data) { /* SData が Int の場合の pretty print */
    printf("SData as Int %d\n",data->body.valInt);
}
void pprintrint_SDataDouble(SData_tp data) { /* SData が Double の場合の pretty print */
    printf("SData as Double %f\n",data->body.valDouble); 
}
void pprintrint_SDataSymbol(SData_tp data) { /* SData が Symbol の場合の pretty print */
    printf("SData as Symbol %s\n",data->body.valSymbol);
}
void pprintrint_SDataComposite(SData_tp data) { /* SData が Composite の場合の pretty print */
    printf("SData as Composite\n");
}

void pprintrint_SData(SData_tp data) { /* tag に応じて、各関数を呼び出す dispatch関数 */
    switch(data->tag) {
    case tagInt:   /* Int の場合 */
	pprintrint_SDataInt(SData_tp data);
        break;
    case tagDouble: /* Double の場合 */
	pprintrint_SDataDouble(SData_tp data);
        break;
    case tagSymbol: /* Symbol の場合 */
	pprintrint_SDataSymbol(SData_tp data);
        break;
    case tagComposite: /* Composite の場合 */
	pprintrint_SDataComposite(SData_tp data);
        break;
    default:
	error(1);
    }
}

2001.11.20/ Tomio KAMADA: kamada@cs.kobe-u.ac.jp