Function definitions
関数定義は、関数本体(宣言と文のシーケンス)を関数名と引数リストに関連付けます。 関数宣言 とは異なり、関数定義はファイルスコープでのみ許可されます(ネストされた関数は存在しません)。
C言語は2つの異なる形式の関数定義をサポートしています:
| attr-spec-seq (オプション) specifiers-and-qualifiers parameter-list-declarator function-body | (1) | ||||||||
| specifiers-and-qualifiers identifier-list-declarator declaration-list function-body | (2) | (C23まで) | |||||||
ここで
| attr-spec-seq | - | (C23) 関数に適用される 属性 のオプションのリスト |
| specifiers-and-qualifiers | - | 以下の組み合わせ: |
| parameter-list-declarator | - | 関数パラメータを指定するために パラメータリスト を使用する関数型の宣言子 |
| identifier-list-declarator | - | 関数パラメータを指定するために 識別子リスト を使用する関数型の宣言子 |
| declaration-list | - | identifier-list-declarator 内のすべての識別子を宣言する一連の宣言。これらの宣言では初期化子を使用できず、許可される唯一の 記憶クラス指定子 は register です。 |
| function-body | - | この関数が呼び出されるたびに実行される、宣言と文の波括弧で囲まれたシーケンスである 複合文 |
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; }
目次 |
説明
関数宣言と同様に、 関数宣言 の場合と同様に、関数の戻り値の型は、 specifiers-and-qualifiers 内の型指定子によって決定され、必要に応じて declarator によって、 宣言 で通常行われるように修飾されることがあります。この戻り値の型は、完全な非配列オブジェクト型または void 型でなければなりません。戻り値の型がcvr修飾される場合、関数型を構築する目的で、その非修飾バージョンに調整されます。
関数宣言と同様に、関数型を構築する目的で、パラメータの型は関数からポインタへ、配列からポインタへと調整され、互換性のある関数型を決定する目的では、すべてのパラメータ型のトップレベルのcvr修飾子は無視されます。
|
関数宣言 とは異なり、無名の仮引数は許可されていません(さもなければ、旧式(K&R)の関数定義で競合が発生します)。関数内で使用されない場合でも、仮引数には名前を付ける必要があります。唯一の例外は、特別な仮引数リスト ( void ) です。 |
(C23まで) |
|
旧式(K&R)の関数定義が削除されたため、関数定義では仮引数を無名にすることができます。無名の仮引数は、関数本体内で名前でアクセスすることはできません。 |
(C23以降) |
int f(int, int); // 宣言 // int f(int, int) { return 7; } // C23までエラー、C23以降OK int f(int a, int b) { return 7; } // 定義 int g(void) { return 8; } // OK: voidはパラメータを宣言しない
関数本体内部では、すべての名前付きパラメータは lvalue 式であり、それらは自動 storage duration と block scope を持ちます。メモリ内でのパラメータのレイアウト(またはメモリに格納されるかどうか)は未規定です:これは calling convention の一部です。
int main(int ac, char **av) { ac = 2; // パラメータは左辺値 av = (char *[]){"abc", "def", NULL}; f(ac, av); }
関数呼び出しの仕組みに関する詳細は function call operator を、関数からの戻り値については return を参照してください。
__func__すべての 関数本体 内で、特別な事前定義変数 __func__ がブロックスコープと静的ストレージ期間を持って利用可能です。これはあたかも開きブレースの直後に以下のように定義されているかのようです: static const char __func__[] = "function name"; この特別な識別子は、時には 事前定義マクロ定数 __FILE__ および __LINE__ と組み合わせて使用されます。例えば、 assert によって使用されます。 |
(C99以降) |
注記
引数リストは明示的に宣言子内に存在しなければならず、typedefから継承することはできません
typedef int p(int q, int r); // pは関数型 int(int, int) です p f { return q + r; } // エラー
|
C89では、 specifiers-and-qualifiers は省略可能であり、省略された場合、関数の戻り値の型はデフォルトで int となる( declarator によって修正される可能性あり)。 さらに、旧形式の定義では、 declaration-list 内のすべてのパラメータに対する宣言は必須ではなかった。宣言が欠落しているパラメータはすべて int 型を持つ。 max(a, b) // a and b have type int, return type is int { return a>b?a:b; } |
(C99まで) |
不具合報告
以下の動作変更に関する欠陥報告書は、以前に公開されたC規格に対して遡及的に適用されました。
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| 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++ documentation
for
Function definition
|
|
C++ documentation
の
Function definition
|