<C言語入門/車載ソフト> 関数
こんにちは、レオハルです。
車載ソフトで利用するC言語入門シリーズ「関数」です。
※通常のC言語解説とは、異なり組込み・車載ソフトに特化した記載があります。ご注意ください。
関数とは
処理のかたまりをブロックでまとめたものを関数と呼びます。
中学数学で出てきた"y=f(x)"のような関数もC言語上の関数として表現することができます。数学の関数と違い、x(引数)を与えるとy(戻り値)が得られるという形だけでなく、引数も戻り値もなく、ただ処理を行うものも関数になります。
入門書などで必ず出てくるprintf()や自分で初めて作るmain()などが関数です。
定義・宣言
関数を作ったり、利用したりするためには、変数と同じように定義や宣言をする必要があります。
プロトタイプ宣言
まず、関数を利用するためには、関数のプロタイプ宣言を行う必要があります。
プロトタイプ宣言がない状態で、対象の関数を利用しようとすると、コンパイルエラーが発生します。コンパイラが対象の関数を認識できていないためです。
ただし、利用箇所の前に、定義してあればコンパイルは通ります。しかし、保守性を考慮した場合には、プロトタイプ宣言をファイルの初めに記載しておくことが推奨されます。
プロトタイプ宣言では、関数の型(戻り値)と名前、引数を宣言します。
引数が複数ある場合には、”,(カンマ)"で区切り、複数
戻り値型 関数名( 引数型 引数名 ) ;
ページの最後に記載している実例の中の例でみると以下の箇所になります。
/* 内部関数プロトタイプ宣言 */ static int s4l_add_chng( int s4_input ) ;
最初の「static」は、内部関数(スタティック関数)であることを示す修飾子です。
変数と同様、ファイル内でのみ利用することができる関数であることを示しています。
戻り値型として「int」、関数名として「s4l_add_chng」、引数として「int s4_input」が続いて宣言されていることが分かります。
また、ファイル外の関数を使用する場合にも、事前にプロトタイプ宣言が必要になります。この場合は、利用する関数の宣言が記載されたヘッダファイルをインクルードする記述が推奨されます。
定義
続いて関数の作り方となる定義方法です。変数と同様に実体となるプログラムをメモリに配置するため定義と呼びます。
定義方法としては、以下のようになります。
戻り値型 関数名( 引数型 引数名 )
{
処理 ;
・
・
return( オブジェクト ) ;
}
戻り値がない場合は、戻り値型が「void」となり、最後の「return文」は不要となります。
ページの最後に記載している実例の中の例で確認してみましょう。
/* main関数定義 */ void vog_main(void) { int s4a_tmp_input1; s4a_tmp_input1 = s4s_base_Value * 2 ; s4g_add_Sum = s4g_add_Sum + s4a_tmp_input1 ; s4s_base_Value = s4l_add_chng( s4a_tmp_input1 ) ; }
/* 内部関数定義 */ static int s4l_add_chng( int s4_input ) { int s4a_result ; s4a_result = s4_input+ 1 ; return( s4a_result ); }
ここでは、二つの関数が定義されています。
一つ目は、戻り値型が「void」、関数名が「vog_main」、引数が「void」となっています。戻り値も引数もない、ただ処理を行うだけの関数になっています。また、この関数には、内部関数を示すstatic が修飾されていないため、外部関数(グローバル関数)であることが分かります。ファイル外の別の関数から呼び出すことが可能です。
二つ目は、戻り値型が「int」、関数名が「s4l_add_chng」、引数が「int s4_input」となっています。先ほどプロトタイプ宣言していた関数の定義部分になっています。
関数の命名
関数の名前の付け方についても、変数と同様に担当するプロジェクトで決められたスタイル規約・コーディング規約に基づいて命名しましょう。変数の命名
事例では、関数名を以下のようにつけています。
vog_main
「vo」:戻り値型=void
「g」:有効範囲=外部関数(グローバル)
「main」:処理内容=メイン処理
s4s_add_chng
「s4」:戻り値型=int(符号あり4バイト)
「s」:有効範囲=内部関数(スタティック)
「add_chng」:処理内容=加算値の変更
なお、関数名は、ソースコード内で重複しないようにしましょう。
ファイル毎にコンパイルされるため、内部関数等は、複数ファイルで同じ名前が出てきてもコンパイルは通りますが、保守性・可読性が低下します。
実例
#include <studio.h> /* 内部関数プロトタイプ宣言 */ static int s4s_add_chng( int s4_input ) ; /* 外部変数定義 */ int s4g_add_Sum ; /* 内部変数定義 */ static int s4s_base_Value ; /* main関数定義 */ void vog_main(void) { int s4a_tmp_input1; s4a_tmp_input1 = s4s_base_Value * 2 ; s4g_add_Sum = s4g_add_Sum + s4a_tmp_input1 ; s4s_base_Value = s4s_add_chng( s4a_tmp_input1 ) ; } /* 内部関数定義 */ static int s4s_add_chng( int s4_input ) { int s4a_result ; s4a_result = s4_input+ 1 ; return( s4a_result ); }
関数に関しては、他にも「ポインタ渡し」や「関数ポインタ」など知っておくべきポイントがあるため、今後どこかでまとめたいと思います。
C言語学習におススメの書籍
【C言語/プログラミング初心者の方】
【入門卒業レベルの方】
【組込み向け】