関数宣言
関数宣言は関数を指示する識別子を導入します。 オプションで関数引数の型 (プロトタイプ) も指定できます。 関数の宣言は (定義と異なり) ファイルスコープだけでなくブロックスコープにも現れることができます。
構文
関数宣言の宣言の構文では、型指定子の並び (宣言子によって修飾されることもあります) は、戻り値の型 (配列型および関数型以外の任意の型にできます) を表し、宣言子は以下の2つの形式のいずれかです。
noptr-declarator ( parameter-list )
|
(1) | ||||||||
noptr-declarator ( identifier-list(オプション) )
|
(2) | (C2x未満) | |||||||
noptr-declarator ( )
|
(3) | (C2x以上) | |||||||
ただし
| noptr-declarator | - | 括弧で囲まれていないポインタ宣言子を除く、任意の宣言子。 この宣言子に含まれる識別子が関数指示子になります。 |
| parameter-list | - | 単一のキーワード void、またはコンマ区切りの引数のリスト (最後に省略記号引数を付けても構いません) のいずれか。
|
| identifier-list | - | コンマ区切りの識別子のリスト (この宣言子が旧形式の関数定義の一部として使用された場合のみ)。 定義でない旧形式の宣言の場合は省略しなければなりません。 |
int max(int a, int b); // 宣言。
int n = max(12.01, 3.14); // OK、 double から int への変換。
int max();
int n = max(true, (char)'a'); // 2つの int (昇格されています) を用いて max を呼びます。
int n = max(12.01f, 3.14); // 2つの double (昇格されています) を用いて max を呼びます。
int max(a, b)
int a, b; { return a>b?a:b; } // 定義は int を期待しています。 2つ目の呼び出しは未定義です。
void から構成される parameter-list を持つ関数宣言と同等です。 つまり、引数を取らない関数を宣言します。説明
関数の戻り値の型 (specifiers-and-qualifiers の型指定子によって決定され、宣言の宣言子によって通常通りに修飾される可能性があります) は、完全非配列オブジェクト型または void 型でなければなりません。
void f(char *s); // 戻り値の型は void です。
int sum(int a, int b); // sum の戻り値の型は int です。
int (*foo(const void *p))[3]; // 戻り値の型は int 3個の配列へのポインタです。
|
関数の戻り値の型は cvr 修飾できません。 あらゆる修飾された戻り値の型は関数の型を構築する目的のためにはその非修飾バージョンに調節されます。 double const foo(void) { return 0.; } // double(void) 型の関数を宣言します。
double (*foop)(void) = foo; // OK、 foop は double(void) へのポインタです。
double const (*foopc)(void) = foop; // OK、 foopc も double(void) へのポインタです。
|
(C17以上) |
関数宣言子は、型指定子および修飾子を共有している限り、他の宣言子と組み合わせられます。
int f(void), *fip(), (*pfi)(), *ap[3]; // 2つの関数と2つのオブジェクトを宣言します。
inline int g(int), n; // エラー、 inline 修飾子は関数専用です。
typedef int array_t[3];
array_t a, h(); // エラー、配列型は関数の戻り値の型にできません。
関数宣言があらゆる関数の外側に現れた場合は、 static が使用されたか以前の static 宣言が可視でない限り、それが導入した識別子はファイルスコープと外部リンケージを持ちます。 宣言が別の関数の内側に現れた場合は、識別子はブロックスコープ (および内部または外部リンケージのいずれか) を持ちます。
int main(void)
{
int f(int); // 外部リンケージ、ファイルスコープ。
f(1); // プログラム中のどこかで定義が利用可能でなければなりません。
}
関数定義の一部でない宣言内の仮引数は名前を持つ必要はありません。
int f(int, int); // 宣言。
// int f(int, int) { return 7; } // エラー、定義では仮引数に名前が必要です。
parameter-list 内のそれぞれの仮引数は単一の変数を導入する宣言ですが、以下の追加の性質を持ちます。
- 宣言子内の識別子は省略可能です (その関数宣言が関数定義の一部でない場合)
int f(int, double); // OK
int g(int a, double b); // これも OK
int f(int, double) { return 1; } // エラー、定義では仮引数に名前が必要です。
- 仮引数で使用可能な記憶域クラス指定子は
registerだけです。 これは関数宣言では無視されますが、関数定義では無視されません。
int f(static int x); // エラー。
int f(int [static 10]); // OK (配列の添字の static は記憶域クラス指定子ではありません)。
- 配列型の仮引数は対応するポインタ型に調節されます。 配列宣言子の角括弧内に修飾子が存在する場合は、そのポインタ型は修飾されます。 (C99以上)
int f(int[]); // int f(int*) を宣言します。
int g(const int[10]); // int g(const int*) を宣言します。
int h(int[const volatile]); // int h(int * const volatile) を宣言します。
int x(int[*]); // int x(int*) を宣言します。
- 関数型の仮引数は対応するポインタ型に調節されます。
int f(char g(double)); // int f(char (*g)(double)) を宣言します。
int h(int(void)); // int h(int (*)(void)) を宣言します。
- 仮引数リストの最後に
, ...を付けても構いません。 詳細については可変長引数関数を参照してください。
int f(int, ...);
- 仮引数は
void型にできません (が、 void へのポインタ型にはできます)。 キーワードvoidのみから構成される特別な仮引数リストが、引数を取らない関数を宣言するために使用されます。
int f(void); // OK。
int g(void x); // エラー。
- 仮引数内に現れる typedef 名としても仮引数名としても扱える識別子は typedef 名として扱われます。
int f(size_t, uintptr_t)は、「size_t」と「uintptr_t」という名前の2つの引数を取る関数の定義を開始する旧形式の宣言子ではなく、 size_t 型と uintptr_t 型の2つの名前のない引数を取る関数のための新形式の宣言子として解析されます。 - 仮引数は不完全型でも構いません。 また、 VLA の記法 [*] を使用しても構いません (C99以上)。 (ただし、関数定義内のものは、配列からポインタおよび関数からポインタへの調節後の仮引数の型は完全でなければなりません。)
関数呼び出しの仕組みに対するその他の詳細については関数呼び出し演算子を、関数からの戻りについては return 文を参照してください。
ノート
|
C++ と異なり、宣言子 int f(void); // 宣言。 引数を取りません。
int g(); // 宣言。 引数は未知です。
int main(void) {
f(1); // コンパイル時エラー。
g(2); // 未定義の動作。
}
int f(void) { return 1; ) // 実際の定義。
int g(a,b,c,d) int a,b,c,d; { return 2; } // 実際の定義。
|
(C2x未満) |
関数定義の場合と異なり、 typedef から仮引数リストを継承できます。
typedef int p(int q, int r); // p は関数型 int(int, int) です。
p f; // int f(int, int) を宣言します。
|
C89 では、 specifiers-and-qualifiers はオプショナルです。 省略された場合は、関数の戻り値の型はデフォルトで *f() { // 関数は int* を返します。
return NULL;
}
|
(C99未満) |
参考文献
- C17 standard (ISO/IEC 9899:2018):
- 6.7.6.3 Function declarators (including prototypes) (p: 96-98)
- C11 standard (ISO/IEC 9899:2011):
- 6.7.6.3 Function declarators (including prototypes) (p: 133-136)
- C99 standard (ISO/IEC 9899:1999):
- 6.7.5.3 Function declarators (including prototypes) (p: 118-121)
- C89/C90 standard (ISO/IEC 9899:1990):
- 3.5.4.3 Function declarators (including prototypes)
関連項目
関数宣言 の C++リファレンス
|