ホーム » スタッフ » 斉藤徹 » 共用体と列挙型

2011年11月
« 10月   12月 »
 12345
6789101112
13141516171819
20212223242526
27282930  

最近の投稿(電子情報)

アーカイブ

カテゴリー

共用体と列挙型

構造体のビットフィールドの説明の次として、共用体・列挙型・typedefなどの説明を行う。

共用体

共用体は、複数のデータの中でどれか1つを保存するような処理で使われる。 基本的に構造体の宣言とほぼ同じだけれど、 各要素のメモリ領域を個別に確保するのが構造体。 共用体は各要素の領域は1つで記憶領域が共用される。

union Data {
char  string[ 10 ] ;
int  number ;
double real ;
} ;
union Data x ;
strcpy( x.string , "hoge" ) ;
x.number = 123 ;
x.real = 2.3456 ;  // 記憶場所は1つだけ

今回は実用っぽいネタということで、以下の処理を示す。 共用体だけでは、中身が解らないので一緒にデータを区別する情報を保存することで、 配列に違うデータを保存する方法。

struct Data {
int type ;
union {  // さりげなく無名共用体...
char string[ 10 ] ;
int  number ;
double real ;
} ;
} ;
void setString( struct Data* p , char s[] ) {
p->type = 1 ;
strcpy( p->string , s ) ;
} ;
void setInteger( struct Data* p , int x ) {
p->type = 2 ;
p->number = x ;
} ;
void setReal( struct Data* p , double x ) {
p->type = 2 ;
p->real = x ;
} ;
void print( struct Data* p ) {
switch( p->type ) {
case 1 : printf( "%s" , p->string ) ; break ;
case 2 : printf( "%d" , p->number ) ; break ;
case 3 : printf( "%f" , p->real ) ; break ;
}
}
void main() {
struct Data table[ 3 ] ;
setString( &table[ 0 ] , "abc" ) ;
setInteger( &table[ 1 ] , 1234 ) ;
setReal( &table[ 2 ] , 23.45 ) ;
for( int i = 0 ; i < 3 ; i++ )
print( &table[ i ] ) ;
}

列挙型

プログラムで、例えば1週間の情報の日月火という曜日を扱う場合、 以下のような記述となることも多い。

#define SUN 0
#define MON 1
:
#define SAT 6
int week ;
for(...) {
if ( week == MON ) {
//月曜日の処理...
}
}

この時、#defineの羅列で数字を規則的に連番を振るのは面倒となる。 これをやってくれるのが列挙型。

enum WEEK {
SUN , MON , TUE , ... , SAT
} ;
enum WEEK week ;
for( ... ) {
if ( week == MON ) {
// 月曜日の処理...
}
}

列挙型変数には、列挙型の要素名の定数以外は代入できないし、 コンパイラによってはswitch文で対応要素の処理が未記載だったら 警告してくれるなど、間違った記載をできないようなチェックが便利。

typedef…

typedefは、自分で定義した型に新しい名前をつける機能。 通常は以下のように使う。

typedef unsigned int  uint_t ;
uint_t x ; // xは符号なしint型となる。
typedef struct DATA {
char name[ 10 ] ;
int  age ;
} Data ;
Data saitoh ;
strcpy( saitoh.name , "saitoh" ) ;
saitoh.age = 47 ;
typedef enum WEEK {
SUN , MON , ... SAT
} Week ;
Week wday ;
wday = MON ;