Определения функций
Определение функции связывает тело функции (последовательность объявлений и операторов) с именем функции и списком параметров. В отличие от объявления функции, определения функций разрешены только на уровне файла (нет вложенных функций).
C поддерживает два различных вида определений функций:
| последовательность_атрибутов(необязательно) спецификаторы_и_квалификаторы декларатор_с_списком_параметров тело_функции | (1) | |
| спецификаторы_и_квалификаторы декларатор_с_списком_идентификаторов список_объявлений тело_функции | (2) | (до C23) |
где
| последовательность_атрибутов | - | (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, он корректируется до своей неквалифицированной версии для целей построения типа функции.
void f(char *s) { puts(s); } // return type is void
int sum(int a, int b) { return a+b: } // return type is int
int (*foo(const void *p))[3] { // return type is pointer to array of 3 int
return malloc(sizeof(int[3]));
}Как и в случае с объявлениями функций, типы параметров корректируются от функций к указателям и от массивов к указателям для целей построения типа функции, а верхнеуровневые cvr-квалификаторы всех типов параметров игнорируются для определения совместимого типа функции.
| В отличие от объявлений функций, безымянные формальные параметры не допускаются (в противном случае возникнут конфликты в определениях функций в старом стиле (K&R)), они должны быть именованными, даже если они не используются в теле функции. Единственным исключением является специальный список параметров | (до 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В теле функции каждый именованный параметр является выражением lvalue, у них есть автоматическая продолжительность хранения и объем блока. Размещение параметров в памяти (или если они вообще хранятся в памяти) не определено: это часть конвенции вызова.
int main(int ac, char **av)
{
ac = 2; // parameters are lvalues
av = (char *[]){"abc", "def", NULL};
f(ac, av);
}См. оператор вызова функции для получения дополнительной информации о механике вызова функции и return для возвращения из функций.
__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, спецификаторы_и_квалификаторы были необязательными, и если они отсутствовали, тип возвращаемого значения функции по умолчанию был Кроме того, в определениях старого стиля не требовалось объявление для каждого параметра в список_объявлений. Любой параметр, объявление которого отсутствовало, имел тип 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 Определения функций (стр.: 113-115)
- Стандарт C11 (ISO/IEC 9899:2011):
- 6.9.1 Определения функций (стр.: 156-158)
- Стандарт C99 (ISO/IEC 9899:1999):
- 6.9.1 Определения функций (стр.: 141-143)
- Стандарт C89/C90 (ISO/IEC 9899:1990):
- 3.7.1 Определения функций
См. также
| Документация C++ по Определению функции |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/function_definition