<C言語入門/車載ソフト> 構造体
こんにちは、レオハルです。
車載ソフトで利用するC言語入門シリーズ「構造体」です。
※通常のC言語解説とは、異なり組込み・車載ソフトに特化した記載があります。ご注意ください。
構造体とは
構造体とは、種類の違う型のデータを複数集め、まとめてメモリに配置できるオブジェクトです。配列でも同様に複数のデータを扱うことができましたが、配列の場合は、同じ型のデータしか取り扱えません。構造体のメリットは、違う型もまとめて取り扱えることにあります。
構造体の定義方法
型の定義
構造体を利用する場合、まず構造体として取り扱う型の定義を行います。また、構造体で扱うデータのことをメンバと呼びます。構造体を定義する際には、取り扱うメンバの定義も同時に行います。
基本の定義方法は、次のようになります。struct を利用します。
struct 構造体型(タグ)名{
型 メンバ1;
型 メンバ2;
:
};
ここで記述している構造体型のことをタグと呼びます。
構造体の実体定義
上記では、型を定義しただけですので、実体となる構造体変数を定義する必要があり、次のように記述します。
struct タグ名 変数名 ;
typedefを利用した定義方法
既存型名に対して別の型名を付けることができるtypedefを利用した方法がよく利用されます。先ほどの定義方法では、変数実体を定義する際に、structを付ける必要がありましたが、typedefを利用して構造体に別名を付けることで省略することができます。
typedef struct タグ名{ 型 メンバ1; 型 メンバ2; : }構造体別型名; 構造体別型名 変数名 ;
また、typedefを使う場合、タグ名の部分は省略することができます。これは、"struct{ 型 メンバ名}”に対して別名の型を定義している形になります。
typedef struct { 型 メンバ1; 型 メンバ2; : }構造体別型名; 構造体別型名 変数名 ;
また、タグ名を省略して構造体を定義した上記の例の場合、次の定義は出来ません。
struct タグ名 変数名 ; /* コンパイルエラー */
struct 構造体別型名 変数名 ; /* コンパイルエラー */
具体的使用例
次に定義した構造体を例をもとに使い方を見ていきます。
typedef struct { s2 s2_gx ; /* 前後G */ s2 s2_gy ; /* 横G */ s2 s2_yaw ; /* ヨー */ u2 u2_ig; /* IG電圧 */ u2 u2_pb; /* バッテリ電圧 */ u4 u4_mil ; /* 走行距離 */ u2 u2_eng ; /* エンジン回転数 */ u1 u1_spd ; /* 車速 */ s2 s2_str; /* 舵角 */ }VehicleInfo;
構造体の初期値設定
構造体の変数宣言と同時に、各メンバの初期値を設定することができます。
/* 初期値設定 */
const VehicleInfo str_VcleDefaultData = { 0, 0, 0, 12, 12, 0, 0, 0, 0 };
構造体の配列
構造体も普通の変数と同様に配列で定義することが可能です。
Vehicleinfo str_VcleANow; /* 現在値 */ Vehicleinfo str_VcleAData[9]; /* 保存データ */
構造体の参照・代入
同じ型の構造体同士であれば、代入処理により、すべての変数を一度に代入することができます。
void init( void ) { u1 u1a_cnt ; str_VcleANow = str_VcleDefaultData ; for( u1a_cnt = 0 ;u1a_cnt < 10 ; u1a_cnt ++){ str_VcleAData[u1a_cnt ] = str_VcleDefaultData ; } }
構造体メンバの参照・代入
構造体の中に定義されている各メンバを直接参照したり、代入したりすることが可能です。メンバを指定する場合には、構造体名の後に".(ピリオド)"を付けてメンバ名を続けることで指定できます。
void vog_VcleInfoGet( VehicleInfo * str_input ); /* 車両情報取得処理 */ void main( void ) { u1 u1a_cnt ; vog_VcleInfoGet(&str_VcleANow ); for( u1a_cnt = 0 ;u1a_cnt < 10 ; u1a_cnt ++){ if( 0 == u1a_cnt ){ str_VcleAData[u1_cnt].u1_spd = str_VcleANow.u1_spd } else{ str_VcleAData[u1_cnt].u1_spd = str_VcleAData[u1_cnt].u1_spd[ u1_cnt - 1] ; } } }
構造体の中の構造体
構造体の中に構造体の型を持つメンバを作ることも可能です。
struct sensor{ s2 s2_gx ; /* 前後G */ s2 s2_gy ; /* 横G */ s2 s2_yaw ; /* ヨー */ }; struct volt{ u2 u2_ig; /* IG電圧 */ u2 u2_pb; /* バッテリ電圧 */ }; typedef struct { struct SENSOR str_sensor : /* センサ値 */ struct VOLT str_volt; /* 入力電圧 */ u4 u4_mil ; /* 走行距離 */ u2 u2_eng ; /* エンジン回転数 */ u1 u1_spd ; /* 車速 */ s2 s2_str; /* 舵角 */ }VehicleInfo;
このように構造体をある意味のある集合体として定義、管理することで、データが使いやすくなったり、可読性を向上させたりすることができます。
ただ、変数を羅列するのではなく、構造を考え、どんなデータをどう持たせるのか考えて、構造体をうまく使っていきたいですね
C言語学習におススメの書籍
【C言語/プログラミング初心者の方】
【入門卒業レベルの方】
【組込み向け】