組み込み技術を向上したい!!

でも組み込み以外にも手を出し始めました・・・

関数化してますか? (C言語)

稀に遭遇することがあるので、ちょっとコメントを・・・。

プログラムが複雑になってくると、例えば、mainの中に全部書くとわけがわからなくなります。

そこで、「関数」としていろいろ部品に分けていくのですが、仕事でプログラムをされている方でも、稀に(わざとかもしれんけどね)ほとんど関数化しない人がいます。

頻繁にバグと闘っている姿を見るので、たぶん、整理するためにも関数化は大事だと思います。

さて、まずは関数の説明ですが、まずは基本的部分から。(あえて配列とか使いません)

int main(void)
{
  int x, y, z;
  int ans1, ans2, ans3;

  ans1 = x + y;
  ans2 = y + z;
  ans3 = x + z;

  return 0;
}

みたいな処理があったとします。良く見てみると、二つの変数を足している処理が3つ記載されていることがわかると思います。

この、「二つの変数を足す処理」を関数化してみましょう。

(まぁ足すだけなのであんまり意味なさそうですが)

int Addition(int a, int b)
{
  int ans;
  ans = a + b;
  return ans;
}

さて、二つの変数を足す関数ができたので、この関数を利用して、最初のプログラムを書き換えてみましょう。

int Addition(int a, int b) ; /* プロトタイプ宣言 */
int main(void)
{
  int x, y, z;
  int ans1, ans2, ans3;

  ans1 = Addition(x, y);
  ans2 = Addition(y, z);
  ans3 = Addition(x, z);

  return 0;
}

今回の例では、あまり効果が分かりにくいですが、関数化する処理が複雑になったときに効果を実感できると思います。

ちなみに Additionの関数は以下のようにもかけます。

int Addition(int a, int b)
{
  return (a + b);
}

お仕事でプログラミングなどをする場合はコーディング規約などのルールがある場合があります。

無い企業もありますが、プログラムの保守性を考慮すると、あった方が良いように思います。

上記の場合は足してreturnするだけなので、良いですが、複雑な計算をすると以下のようになって、可読性が悪くなる可能性があります。(もはや足し算ではないけどね)

(式をみてピンと来た人は友達になれそう)

int Addition(int a, int b)
{
  return ((1 / ((1/a) - ( log((double)(1500/(b* 1000) / (3.0 -b)))/3350 ))) - 273.15);
}

なので、return の値に直接数式を持ってくるのは個人的には苦手かなぁ・・・。

あと、ついでですが、上記のような Addition関数の場合は関数の呼び出し元(今回の場合はmain文)で値を受け取るにはreturn値を得るしか方法がないので、答えは一つしか得られません。

では、以下のようなmain文の中身を関数化するにはどうすると都合が良いでしょうか?

int main(void)
{
  int x, y, z;
  int ans1, ans2, ans3;
  int ans4, ans5, ans6;

  ans1 = x + y;
  ans2 = y + z;
  ans3 = x + z;

  ans4 = x - y;
  ans5 = y - z;
  ans6 = x - z;

  return 0;
}

AdditionのほかにSubtraction(引き算)の関数を作ると考えてしまうかも知れませんが、もう少し楽できる方法があります。

int AddSub(int a, int b, int *ans_add, int *ans_sub);

というような関数を宣言してみます。 *がついて宣言されている変数はポインタです。

関数の中身は以下のようにしてましょう。

int AddSub(int a, int b, int *ans_add, int *ans_sub)
{
  *ans_add = a + b;
  *ans_sub = a - b;

  return 0; /* 今回は未使用 */
}

すると、main文は以下のように書き変えることが可能です。

int AddSub(int a, int b, int *ans_add, int *ans_sub);
int main(void)
{
  int x, y, z;
  int ans1, ans2, ans3;
  int ans4, ans5, ans6;

  AddSub(x, y, &ans1, &ans4); /* 変数のアドレスを利用する */
  AddSub(y, z, &ans2, &ans5);
  AddSub(x, z, &ans3, &ans6);

  return 0;
}

関数化する効果が少し見えてきた気がしますね。

次はポインタについて少し解説します。