昨年度のテスト問題で、構造体の配列の作り方とそのイメージ図についての 問題で質問が多かったので、解説を行った。
//2件のComplex型を配列に入れる。 struct Complex { double re , im ; } ; // (A) 単純な配列 struct Complex table[ 2 ] ; // (B) 配列サイズを可変にする場合 struct Complex* table ; table = (struct Complex*)malloc( sizeof( struct Complex ) * 2 ) ; if ( table != NULL ) { table[0].re = 1 ; table[0].im = 2 ; table[1].re = 3 ; table[1].im = 4 ; } // (C)実体参照をポインタにする場合 struct Complex* table[ 2 ] ; table[0] = (struct Complex*)malloc( sizeof( struct Complex ) ) ; if ( table[0] != NULL ) { table[0]-> = 1 ; table[0]-> = 2 ; } table[1] = (struct Complex*)malloc( sizeof( struct Complex ) ) ; if ( table[1] != NULL ) { table[1]-> = 3 ; table[1]-> = 4 ; } // (D)可変配列サイズでポインタ参照 struct Complex** table ; table = (struct Complex**)malloc( sizeof( struct Complex* ) * 2 ) ; if ( table != NULL ) { table[0] = (struct Complex*)malloc( sizeof( struct Complex ) ) ; if ( table[0] != NULL ) { table[0]-> = 1 ; table[0]-> = 2 ; } table[1] = (struct Complex*)malloc( sizeof( struct Complex ) ) ; if ( table[1] != NULL ) { table[1]-> = 3 ; table[1]-> = 4 ; } }
(A)は、最も基本の配列。 (B)は、配列サイズが実行時に決められない時で、 可変配列サイズの場合にとる方法。 (C)は、構造体のComplex型で、もし巨大なメモリを消費する場合、 例えば配列のソートでデータ入れ替えがある場合、 巨大構造体であれば、巨大なメモリをコピーするのは時間がかかる。 (C)の例の様にポインタで実体を参照する方法であれば、 データ入れ替えもポインタの入れ替えだけで可能となる。 (D)は、(B)と(C)のテクニックのあわせ技。 この様に、配列サイズが可変なのか、実体入れ替えが容易なのか… という状況に応じて、これらのデータ構造の実装方法を選べることが重要。