Function definitions
Определение функции связывает тело функции (последовательность объявлений и операторов) с именем функции и списком параметров. В отличие от объявления функции , определения функций разрешены только на уровне файла (вложенные функции не допускаются).
C поддерживает две различные формы определений функций:
| 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 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; // параметры являются lvalues av = (char *[]){"abc", "def", NULL}; f(ac, av); }
См. оператор вызова функции для получения дополнительной информации о механике вызова функции и 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 | the return type might be qualified | the return type is implicitly disqualified |
Ссылки
- Стандарт 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++ документация
для
Определение функции
|