関数定義
関数定義は、関数本体(宣言と文のシーケンス)を関数名と仮引数リストに関連付けます。関数宣言とは異なり、関数定義はファイルスコープでのみ許可されます(ネストされた関数はありません)。
Cは2つの異なる形式の関数定義をサポートしています。
| 属性指定子シーケンス(オプション) 指定子・修飾子 仮引数リスト宣言子 関数本体 | (1) | ||||||||
| 指定子・修飾子 識別子リスト宣言子 宣言リスト 関数本体 | (2) | (C23まで) | |||||||
ここで、
| attr-spec-seq | - | (C23以降)関数に適用される、属性のオプションのリスト |
| 指定子・修飾子 | - | 以下の組み合わせ |
| 仮引数リスト宣言子 | - | 関数の仮引数を指定するために仮引数リストを使用する、関数型の宣言子 |
| 識別子リスト宣言子 | - | 関数の仮引数を指定するために識別子リストを使用する、関数型の宣言子 |
| 宣言リスト | - | 識別子リスト宣言子内のすべての識別子を宣言する宣言のシーケンス。これらの宣言は初期化子を使用できず、許可される唯一の記憶域クラス指定子はregisterです。 |
| 関数本体 | - | 複合文、つまり波括弧で囲まれた宣言と文のシーケンスであり、この関数が呼び出されるたびに実行されます。 |
int max(int a, int b) { return a>b?a:b; } double g(void) { return 0.1; }
int max(a, b) int a, b; { return a>b?a:b; } double g() { return 0.1; }
目次 |
[編集] 説明
関数宣言と同様に、指定子・修飾子内の型指定子によって決定され、宣言で通常行われるように宣言子によって修飾される可能性のある関数の戻り値の型は、完全な非配列オブジェクト型または型voidでなければなりません。戻り値の型がcvr修飾されている場合、関数型を構築する目的で、その非修飾版に調整されます。
関数宣言と同様に、仮引数の型は、関数型を構築する目的で関数からポインタへ、配列からポインタへと調整され、すべての仮引数型のトップレベルのcvr修飾子は、互換性のある関数型を決定する目的で無視されます。
|
関数宣言とは異なり、無名仮引数は許可されません(さもなければ、旧形式(K&R)の関数定義で競合が発生するため)。関数内で使用されない場合でも、名前を付ける必要があります。唯一の例外は、特別な仮引数リスト(void)です。 |
(C23まで) |
|
旧形式(K&R)の関数定義が削除されたため、関数定義で仮引数を無名にすることができます。無名仮引数は、関数本体内で名前によってアクセスできません。 |
(C23以降) |
int f(int, int); // declaration // int f(int, int) { return 7; } // Error until C23, OK since C23 int f(int a, int b) { return 7; } // definition int g(void) { return 8; } // OK: void doesn't declare a parameter
関数本体内では、名前付きの各仮引数は左辺値式であり、自動記憶域期間とブロックスコープを持ちます。メモリ内での仮引数のレイアウト(またはメモリに格納されるかどうか)は未規定です。これは呼び出し規約の一部です。
int main(int ac, char **av) { ac = 2; // parameters are lvalues av = (char *[]){"abc", "def", NULL}; f(ac, av); }
関数呼び出しの仕組みに関するその他の詳細については関数呼び出し演算子を、関数からの復帰についてはreturnを参照してください。
__func__すべての関数本体内で、ブロックスコープと静的記憶域期間を持つ特別な定義済み変数__func__が、開始波括弧の直後で次のように定義されているかのように利用できます。 static const char __func__[] = "function name"; この特別な識別子は、 |
(C99以降) |
[編集] 注釈
引数リストは宣言子に明示的に存在しなければならず、typedefから継承することはできません。
typedef int p(int q, int r); // p is a function type int(int, int) p f { return q + r; } // Error
|
C89では、指定子・修飾子はオプションであり、省略された場合、関数の戻り値の型は(宣言子によって修正される可能性はありますが)デフォルトでintになりました。 さらに、旧形式の定義では宣言リスト内のすべての仮引数に宣言が必要ではありませんでした。宣言が欠落している仮引数は型intを持ちました。 max(a, b) // a and b have type int, return type is int { return a>b?a:b; } |
(C99まで) |
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に発行されたC規格に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| DR 423 | C89 | 戻り値の型が修飾される可能性がある | 戻り値の型は暗黙的に非修飾になる |
[編集] 参照
- C17標準 (ISO/IEC 9899:2018)
- 6.9.1 関数定義 (p: 113-115)
- C11標準 (ISO/IEC 9899:2011)
- 6.9.1 関数定義 (p: 156-158)
- C99標準 (ISO/IEC 9899:1999)
- 6.9.1 関数定義 (p: 141-143)
- C89/C90標準 (ISO/IEC 9899:1990)
- 3.7.1 関数定義
[編集] 関連項目
| 関数定義のC++ ドキュメント
|