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

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

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

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

<C言語入門/車載ソフト> if文

f:id:Vefortec:20200504201222j:plain

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

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

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

 基本的な使い方

if文とか出てくると、プログラム作りだしたなって気がしてきますよね。
プログラミングの基礎として、「順次」「分岐」「反復」があります。
if文は、「分岐」の役割を担う文です。

if文の使い方は、以下のようになります。

if( 条件式 ){
    条件式が真のときに実行する処理
}
else{
  条件式が偽のときに実行する処理
}

条件文には、2つのデータが等しいか等しくないかや、大小関係などの判定が入ります。条件が真の場合をtrue、偽の場合をfalseと表現することもあります。

一つ例を挙げて解説していきます。

u1 u1g_func1( u1 u1_input )
{
  u1 u1a_result ;

  if( 10 >= u1_input  ){
    u1a_result = 0 ;
  }
  else{
    u1a_result = 1 ;
  }
  return( u1a_result ) ;
}

この関数は、引数として渡されたデータが、10以下の場合に0、10より大きい場合に1を返します。
 ちなみに、条件式の右辺、左辺はどちらが変数、どちらが定数といった決まりは無く、どちらでもコンパイルは通ります。ただし、よくある間違いとして「変数==定数」を「変数=定数」と条件式に書いてしまうことがあります。この場合、コンパイルエラーも発生しないため、気づきにくいバグの1つになります。これをケアする小技として、左辺に定数、右辺に変数を記載するようにします。これにより、「定数=変数」は、代入ができないので、コンパイルエラーで検出することができます。上記例でも、意図的に定数を左辺に書くようにしています。

 

多分岐

if文での条件分岐は、2つだけに限定されていません。3つ以上の分岐を用意することもできます。その場合には、「else if」を利用します。記述例を次に記載します。

u1 u1g_func2( u1 u1_input )
{
  u1 u1a_result ;

	if( ( u1_input % 5 ) == 4 ){
		u1a_result = 4 ;
	}
	else if( ( u1_input % 5 ) == 3 ){
		u1a_result = 3 ;

	}
	else if( ( u1_input % 5 ) == 2 ){
		u1a_result = 2 ;

	}
	else if( ( u1_input % 5 ) == 1 ){
		u1a_result = 1 ;
	}
	else{
		u1a_result = 0 ;
	}
	return( u1a_result ) ;
}

この関数では、入力されたデータを5で割った時の余りが返されます。
※「return ( u1_input % 5);」でいいんですが、気にしない。

ここでワンポイント。
「else if文」を利用した最後には、必ず「else」を付けるようにしましょう。コーディングルールをチェックするツールなんかで違反だと怒られます。これは、elseを書き忘れているのか、elseが発生しないのかを明確にする目的と、万が一想定外の動作となった場合の安全を考慮する目的があります。
組込み系の場合、「プログラムは、記述通りに必ず動く」と思っていてはいけません。
特に車載ソフトの場合、人命にかかわることもあるので、「想定外の動きでした」では、許されません。割り込み処理でメモリが上書きされてしまう、外部からのノイズでメモリが化ける、メモリが経年劣化で故障するなど、記述通りに動かないシーンがあります。

ネスト

複数の条件を重ねてチェックしたい場合、if文の中にさらにif文を記述することがあります。これをネスト(入れ子)と言います。if文の中のif文以外にも、関数の中でさらに関数を呼ぶ場合などもネストと呼びます。ネスト構造が深いとプログラムが読みにくくなるため、一定以下となるよう心がけましょう。

ネストしているif文の例を次に記載します。

u1 u1g_func2_1( u1 u1_input )
{
  u1 u1a_result ;

  if( 100 <= u1_input  ){
    if( 200 > u1_input  ){
      u1a_result = 1;
    }
    else{
      u1a_result = 0 ;
  }
  else{
    u1a_result = 0 ;
  }
  return( u1a_result ) ;
}

この関数では、100以上、200未満のデータが入力された場合に1を返し、それ以外の場合に0を返します。if文がtrueの場合の処理にif文を入れましたが、falseの場合、elseの処理の中でも同様に記述できます。

複数条件

条件式には、複数の条件を記述し、&& や || でつないで記述することも可能です。
先ほどのネスト構造をとらなくても複数条件を使うことで、同じ処理を作ることが可能です。

u1 u1g_func3_2( u1 u1_input )
{
  u1 u1a_result ;

  if(    ( 100 <= u1_input )
      && ( 200 > u1_input  ) ){
    u1a_result = 1;
  }
  else{
    u1a_result = 0 ;
  }
  return( u1a_result ) ;
}

ネストされていたif文を&&で繋げることで同様の処理が実現できました。
自分的な使い分けのポイントは、それぞれの条件の意味を考えることだと思っています。2条件で1つの判定のようなものは、まとめます。逆に、何かの条件の前提条件のように独立したそれぞれの判定の場合には、可読性・保守性を考え、ネストさせるようにしています。どちらの場合も多すぎる・深すぎる場合は、読みにくくなる&バグのもとなので注意しましょう。

あと個人的に分かりやすいかなと思っている書き方を一つ。
条件文の中に複数条件を記載する場合は、"("の位置を上下で合わせて書いてあげるとわかりやすいです。

/* おススメ記載例 */
if
( ( 10 < a ) && ( ( 5== b) || ( 8 = b) ) && ( ( ( c < a ) && ( 4 < c ) ) || ( ( c < b ) && ( 6 > c ) ) ) ){ /* true */ }
/* 嫌いな例 */ if( ( 10 < a ) && ( ( 5== b) || ( 8 = b) ) && ( ( ( c < a ) && ( 4 < c ) ) || ( ( c < b ) && ( 6 > c ) ) ) ){ /* true */ }

プログラムもブログと一緒で縦に長くなります。
横に続くと読みにくいと思いませんか?

 

以上、if文に関する組込み向け解説でした。

 

 

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

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

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

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

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

【入門卒業レベルの方】

苦しんで覚えるC言語

苦しんで覚えるC言語

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

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

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

独習C 第4版

 

 【組込み向け】

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

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