関数定義 には、関数宣言と関数本体が含まれます。
C 関数定義の構文は、以下のとおりです。
.--------------------. V | >>---+-type_specifier-+-+--function_name------------------------> +-extern---------+ '-static---------' >--(--+---------------------------------------+--)--------------> | .-,---------------------. | | V | | '---parameter_declaration-+--+--------+-' '-,--...-' >--| function_body |------------------------------------------->< function_body: |--block_statement----------------------------------------------|
C++ 関数定義の構文は以下のとおりです。
.--------------------. V | >>---+-type_specifier-+-+--function_name------------------------> +-extern---------+ '-static---------' >--(--+---------------------------------------+--)--------------> | .-,---------------------. | | V | | +---parameter_declaration-+--+--------+-+ | '-,--...-' | '-...-----------------------------------' >--+----------+--+-------------------------+--------------------> +-const----+ '-exception_specification-' '-volatile-' >--| function_body |------------------------------------------->< function_body: |--+-| body |--------------------------+------------------------| '-try--| body |--| catch_handlers |-' body: |--+---------------------------------+--block_statement---------| '-:--constructor_initializer_list-' catch_handlers: .---------------------------------------------------------. V | |----catch--(--+-parameter_declaration-+--)--block_statement-+--| '-...-------------------'
どちらの言語でも、関数定義には以下が含まれます。
int f(int a, int b) { return a + b; }
C++ 関数定義には、以下のものを任意に含めることができます。
class A { int x; char y; public: A() : x(0), y('c') { } };
関数は、それ自体によって、または他の関数によって呼び出すことができます。 デフォルトにより、関数定義は、外部結合を持っていて、 他のファイルで定義された関数によっても呼び出すことができます。 static のストレージ・クラス指定子は、関数名はグローバル・スコープだけを持っていて、 同じ変換単位内からのみ直接起動できるということを意味します。
static をこのように使用することは、C++ の場合は推奨できません。
その代わりに、関数を名前なしネーム・スペースに入れます。
C では、関数定義
に外部結合と int 型の戻りの型がある場合は、extern int func();
という暗黙の宣言が想定されるので、関数が可視になる前にその関数を呼び出すことができます。
C++ との互換性を保つためには、プロトタイプを使ってすべての関数を宣言する必要があります。
関数が値を戻さない場合は、型指定子としてキーワード void を使用してください。
関数が引き数をまったく取らない場合は、空のパラメーター・リストではなくキーワード
void を使用して、関数に引き数が渡されないことを示してください。C では、
空のパラメーター・リストを持つ関数は、受け取るパラメーター数が不明の関数を意味しますが、C++
では、その関数はパラメーターを取らないことを意味します。
C では、関数を構造体または共用体のメンバーとして宣言することはできません。
関数宣言の互換性
所定の関数についての宣言はすべて互換性がなければなりません。 つまり、戻りの型が同じで、パラメーターの型が同じです。
型の互換性という考え方は、C のみに関係があります。2 つの関数型に互換性を持たせるには、
戻りの型に互換性を持たせる必要があります。
両方の関数型がプロトタイプなしで指定されている場合
は、このことが唯一の要件になります。
プロトタイプ付きで宣言されている 2 つの関数の場合は、複合型は次の追加要件を 満たす必要があります。
そして、宣言子指定子のシーケンスで [*] 表記を使用して、可変長配列型を指定することができます。
関数宣言子が関数定義の一部ではない場合は、パラメーターの型は不完全型を持つことができます。 このパラメーターは、その宣言子指定子のシーケンスで [*] 表記を使用して、可変長配列型を 指定することもできます。互換性のある関数プロトタイプ宣言子の例を次に示します。
double maximum(int n, int m, double a[n][m]); double maximum(int n, int m, double a[*][*]); double maximum(int n, int m, double a[ ][*]); double maximum(int n, int m, double a[ ][m]);
関数定義の例
次の例は、関数 sum の定義です。
int sum(int x,int y) { return(x + y); }
関数 sum には、外部結合があり、int 型のオブジェクトを戻し、 x および y と宣言された int の 2 つのパラメーターがあります。 この関数本体には、x と y の合計を戻す 1 個のステートメントが入っています。
以下の例において、ary は、2 つの関数ポインターの配列です。 互換性を保つためには、この例では ary に割り当てられた値に対して、型キャストが行われます。
#include <stdio.h> typedef void (*ARYTYPE)(); int func1(void); void func2(double a); int main(void) { double num = 333.3333; int retnum; ARYTYPE ary[2]; ary[0]=(ARYTYPE)func1; ary[1]=(ARYTYPE)func2; retnum=((int (*)())ary[0])(); /* calls func1 */ printf("number returned = %i¥n", retnum); ((void (*)(double))ary[1])(num); /* calls func2 */ return(0); } int func1(void) { int number=3; return number; } void func2(double a) { printf("result of func2 = %f¥n", a); }
次に、上記の例の出力を示します。
number returned = 3 result of func2 = 333.333300
関連参照