自動車エンジニアのアップデート

自動車エンジニアのアップデート

自動車部品メーカー勤務ソフトエンジニアの情報発信ブログ

~ 車載 ソフト エンジニア の 情報発信 ブログ ~

<C言語入門/車載ソフト> 共用体

f:id:Vefortec:20200504201222j:plain

こんにちは、レオハルです。

車載ソフトで利用するC言語入門シリーズ「構造体」です。

※通常のC言語解説とは、異なり組込み・車載ソフトに特化した記載があります。ご注意ください。

共用体とは

構造体と似た機能として紹介されることの多いデータ定義です。
全然違うと思うんですけどね。
共用体は、名前にもあるようにメモリ領域を共用するデータ構造です。
ひとつのメモリ領域に複数の型の変数を割り当て、利用することができます。
同じ領域に複数の型でアクセスしたい場合に利用すると便利です。

共用体の定義方法

型の定義

共用体を利用する場合、構造体と同様に共用体として取り扱う型の定義を行います。

union 共用体型(タグ)名{
  型 メンバ1;
  型 メンバ2;
 ・・・ };
共用体の実体定義

上記は、型の定義だけです。
実体となる変数を定義するため、次の記述を行います。

union タグ名 変数名;
typedefを利用した定義方法

共用体についても、typedefを利用して別の型名を付けることができます。typedefを利用して付けた型名で共用体の実体を定義する場合、頭のunionは不要です。

typedef union タグ名{
 型 メンバ1;
型 メンバ2;
 ・・・ }共用体別型名;

共用体別型名 変数名;

具体的使用例

実例を挙げて、共用体の利用方法を確認します。

定義・参照・代入

union un_ldata{
  u1 byte[4];
  u2 word[2];
  u4 dword;
};

union un_ldata un_LongData;
void main( void ){
  u1 u1a_tmp_byte[4];
  u2 u2a_tmp_word[2];

  un_LongData.dword = 0x12345678;

  u1a_tmp_byte[0] = un_LongData.byte[0] ;
  u1a_tmp_byte[1] = un_LongData.byte[1] ;
  u1a_tmp_byte[2] = un_LongData.byte[2] ;
  u1a_tmp_byte[3] = un_LongData.byte[3] ;

  u2a_tmp_word[0] = un_LongData.byte[0] ;
  u2a_tmp_word[1] = un_LongData.byte[1] ;
}

 4byteのメモリ領域を共用体として確保します。イメージとして、次のような形です。

f:id:Vefortec:20200530091821p:plain

共用体メモリ配置イメージ

構造体と組み合わせた使い方

また構造体を利用して、上位・下位のアドレスに簡単にアクセスできるような記述方法も可能です。

typedef struct {
  u1 u1_LL;
  u1 u1_LH;
  u1 u1_HL:
  u1 u1_HH;
}strby;

typedef struct{ u2 u2_Low; u2 u2_high; }strwd;
typedef union{ u4 u4_dword; strby str_byte; strwd str_word; }unidwd; unidwd uni_Data;
void main( void ){
u2 u2a_tmp ; u4 u4a_result ;

/* step1 */ uni_Data.str_byte.u1_LL = 0x12; uni_Data.str_byte.u1_LH = 0x34; uni_Data.str_byte.u1_HL = 0x56; uni_Data.str_byte.u1_HH = 0x78;

/* step2 */
u2a_tmp = uni_Data.str_word.u2_Low ;
uni_Data.str_word.u2_Low = uni_Data.str_word.u2_high ;
uni_Data.str_word.u2_high = u2a_tmp ;

u4a_result = uni_Data.u4_dword ;
}

 4バイト長の共用体に、1バイトずつ値を代入しています。
その後、2バイトでアクセス、上位下位を入れ替えました。
最終的に4バイトで結果をオート変数に代入しています。
イメージとしては、以下のようになります。

f:id:Vefortec:20200530163121p:plain

ビットフィールド

構造体・共用体を利用して、ビット事のアクセスと1バイトでのアクセスを可能にすることもできます。例えば、何かの判定結果をビット事に設定し、読み出しはバイトで行うといったことが可能になります。さらに、defineで変数・ラベル名を置き換えて、可読性を上げるといった工夫もあります。

typedef struct{
  u1 b0:1 ;
  u1 b1:1 ;
  u1 b2:1 ;
  u1 b3:1 ;
  u1 b4:1 ;
  u1 b5:1 ;
  u1 b6:1 ;
  u1 b7:1 ;
}byte_b;

typedef union{
  byte_b str_bit ;
  u1 u1_data;
}byte_data;

byte_data uni_BitField;

#define flg_Sample_DataA    uni_BitField.str_bit.b0 
#define flg_Sample_DataB    uni_BitField.str_bit.b1
#define flg_Sample_DataC    uni_BitField.str_bit.b2 
#define flg_Sample_DataD    uni_BitField.str_bit.b3
#define flg_Sample_DataE    uni_BitField.str_bit.b4
#define flg_Sample_DataF    uni_BitField.str_bit.b5
#define flg_Sample_DataG    uni_BitField.str_bit.b6 
#define flg_Sample_DataH    uni_BitField.str_bit.b7 
#define u1g_Sample_DataAll  uni_BitField.u1_data

 

同じアドレスに複数の型のメンバを設定することで、型を変えて読み書きすることができるようになります。メモリを意識して開発を進める組込み系、車載系ソフト開発では、うまく使いこなせるようになっておきたいですね。
また、メモリ資源の少ないマイコンでは、ビットフィールドを使う場面も出てくるため、使われている場面に出くわしたら、確認してみましょう。

 

C言語学習におススメの書籍

C言語/プログラミング初心者の方】

スッキリわかるC言語入門

スッキリわかるC言語入門

  • 作者:中山 清喬
  • 発売日: 2018/06/22
  • メディア: 単行本(ソフトカバー)
 

【入門卒業レベルの方】

苦しんで覚えるC言語

苦しんで覚えるC言語

  • 作者:MMGames
  • 発売日: 2011/06/24
  • メディア: 単行本
 
新・明解C言語 入門編 (明解シリーズ)

新・明解C言語 入門編 (明解シリーズ)

  • 作者:柴田 望洋
  • 発売日: 2014/08/09
  • メディア: 単行本
 
独習C 第4版

独習C 第4版

 

 【組込み向け】

組込みエンジニアの教科書

組込みエンジニアの教科書