第1章 「やさしい入門」
1.7 関数

C言語における関数とはまとまった処理を簡単に利用できるように一つの手続きにまとまめたものです。
すでにprintfやputcharなどの関数を利用してきました。
このように定義済みの関数もありますが、自分で関数を作ることもできます。
本項では関数の作り方を学びます。

プログラムの目的

べき乗を行う関数を作成する
関数名はpowerとし、第一引数xに底を第二引数yに指数を入れる。
例として第一引数x=2、第二引数y=5とすると2の5乗=32の答えが求まる。

ソースコード

解説

前回までのソースコードと比べ、大分華やかになりました。
以前からコメント行の大切さを話してきましたが、今回はソースコード全体の書き方についてもご説明したいと思います。

①ソースヘッダ
//=============================================================================
//=============================================================================
/*! @file function.cpp
@brief プログラミング言語C 1.7 関数
@author ヨイモノローグのプログラミング教室
@date 2020/11/21
@par 履歴

Copyright (C) 2020 yoimonologue. All rights reserved.

*/
//=============================================================================
//=============================================================================

ソースファイルの先頭に入れるコメントです。
コメント文なのでプログラム(コンパイル)には何の影響も及ぼしません。
ヘッダ文などと呼ばれることも多いのですが、このファイル全体の説明を記述します。
どのように書いても良いのですが、パターンを決めた方が良いでしょう。
僕のパターンはこの書き方ですね。
これには理由があり、ソースコードから自動でドキュメントを生成するツールDoxgenを利用するため
ツールが理解出来るようなキーワードを入れている為です。

簡単に説明すると上から
@file ソースファイル名
@brief このソースファイルの説明
@author 著者
@data 作成日
@aar 修正履歴の記入

著作権表示について
日本の法律では著作権表示をしなくてもソースコードを書いた時点で著作権が発生します。
しかしすべての国でこのようになっている保証が無いため著作権表示は入れた方が良いと思います。

Copyright (C) 2020 yoimonologue. All rights reserved.

Copyrightと(C)は同じ意味なのでダブるのですが慣例にならっています。
尚(C)は本来©と書くべきなのですが©は環境依存文字のため(C)としています。
yoimonologueの部分は著作者。

「All rights reserved.」はブエノスアイレス条約に基づく著作権表示。
日本はブエノスアイレス条約に加盟していないので効力無しだが慣例に従っています。

②関数ヘッダ
//=============================================================================
/*!
@brief べき乗取得関数
@return int べき乗結果
@note 指数部は正の値のみ
@author yoimonologue
@date 2020/11/20
@par 履歴
*/
//=============================================================================

関数の先頭に入れるコメントです。
こちらもファイルヘッダ同様にプログラムには影響を及ぼしません。
このヘッダを読むだけで関数の機能がわかるような内容を記載します。
書き方は自由ですが、ファイルヘッダ同様にDoxgenで利用しやすいように記述しています。

@brief 関数名
@return 関数の戻り値の説明
@note 注意事項など
@author 著者
@data 作成日
@aar 修正履歴の記入

③関数の定義
基本的な関数の定義は以下のようになっています。
int power (int base, unsigned int exp)

先頭のintはこの関数の戻り値の型を示しています。
戻り値とは関数が処理を行った結果です。
関数には必ず戻り値が必要です。
無い場合はvoidと書きます。
ちなみにK&Rが書かれたANSIでは戻り値無しも許可されていました。

powerは関数名です。
関数名の次が引数です。
引数はこのように、カッコで囲みます(int base, ununsigned int exp)
引数それぞれは、型と引数名で定義、次の引数との間はカンマ’,’でつなぎます。

関数の本文は{から}までになります。

④今回の定義
int power (int base //!< [in]底
,unsigned int exp //!< [in]指数
)
関数の定義はこのように複数行に分けて記述することが可能です。
関数ヘッダに関数の概略説明を書きましたが、引数のそれぞれに関しての説明はここに記載します。
もちろん関数ヘッダに記載しても良いのですが、関数の設計変更などで引数が増えたり減ったりした場合、関数ヘッダを直し忘れることも考えられます。
そこで引数の横に直接コメントする方法を推奨します。
今回の引数はこの関数への入力として使っていますが、実は引数に結果を渡すことも可能です。
この方法については今後説明しますが、このように入力/出力の可能姓があるのでソースコードを読まなくても使い方がわかるように入力出力を明示します。
この//!< [in]のような記載方法もdoxgenに則っています。

僕独特の記述の仕方なのですが
,unsigned int exp //!< [in]指数
のように’,’を先頭に置くようにしています。

一般的にはこのようにbaseの後ろに,を置きます。
int power (int base, //!< [in]底
unsigned int exp //!< [in]指数
)

僕がこのように書く理由は、例えば設計変更でexp引数が不要になった場合を考えて見て下さい。
行削除でexp行を消すだけではダメで、baseの後ろのカンマ’,’も消す必要があります。
僕の書式ではexp行を消すだけで終了です(先頭に,があるから)

追記する場合、最後の行をコピーして、次の行に貼り付け修正するだけで済み。

⑤result *= base;
これは result = result * base;と同じ意味です。
短く記述できるので一般的にこのように書くことが多いと思います。

⑥return result;
関数では戻り値をreturn 戻り値で記述します。
戻り値が無い場合はreturn;のみ
明らかに関数の最後の場合はreturnも不要です。

⑦関数の呼び出し
これは今まで学習してきたように関数名(引数)で呼び出します。
int ret = power(2,i);で関数を呼び出し戻り値をretに入れています。

⑧プロトタイプ宣言
C言語のコンパイラでは自分より後ろの関数はそのままでは認識出来ないのでプロトタイプ宣言をする必要があります。
例えば今回のサンプルプログラムをこのような順で書くとコンパイルエラーになります。
理由はmainの中でpower関数を呼び出していますが、コンパイラからみるとまたpowerが無いためエラーになるのです。

main()
{
power()

}

power()
{

}

プロトタイプ宣言とは事前にコンパイラに関数の型を教えることです。
型とは関数名、戻り値、引数の型です。
今回ではプロトタイプはこのように記述します。
int power (int base,unsigned int exp);

引数の変数名は不要ですのでこのように記述しても構いません
int power (int base,unsigned int exp);

⑨プロトタイプを書かないために
このようにプロトタイプ宣言が必要なのですが、呼び出し順を考えることでプロトタイプ宣言が不要になります。
今回のサンプルプログラムでも呼び出し元であるmain関数を最後に書くことでプロトタイプ宣言を不要にしています。
プロトタイプ宣言は関数の引数を変更する度に同時に行う必要があり面倒で間違いの元です。

呼ばれる側の関数をファイルの上に記述することでプロトタイプ宣言が不要になりますので是非実践して下さい

動作の確認

関数を走らせると2の1乗から9乗の答えが求まります

2の0乗 = 1
2の1乗 = 2
2の2乗 = 4
2の3乗 = 8
2の4乗 = 16
2の5乗 = 32
2の6乗 = 64
2の7乗 = 128
2の8乗 = 256
2の9乗 = 512

今回はここまで