構造体のビットフィールドの説明の次として、共用体・列挙型・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 ;