A function declaration introduces an identifier that designates a function and, optionally, specifies the types of the function parameters (the prototype). Function declarations (unlike definitions) may appear at block scope as well as file scope.
In the declaration grammar of a function declaration, the type-specifier sequence, possibly modified by the declarator, designates the return type (which may be any type other than array or function type), and the declarator has one of two forms:
noptr-declarator ( parameter-list ) | (1) | |
noptr-declarator ( identifier-list(optional) ) | (2) |
where.
noptr-declarator | - | any declarator except unparenthesized pointer declarator. The identifier that is contained in this declarator is the identifier that becomes the function designator. |
parameter-list | - | either the single keyword void or a comma-separated list of parameters, which may end with an ellipsis parameter |
identifier-list | - | comma-separated list of identifiers (only if this declarator is used as part of old-style function definition), must be omitted for old-style declarations that are not definitions. |
int max(int a, int b); // declaration int n = max(12.01, 3.14); // OK, conversion from double to int
int max(); int n = max(true, (char)'a'); // calls max with two int args (after promotions) int n = max(12.01f, 3.14); // calls max with two double args (after promotions) int max(a, b) int a, b; { return a>b?a:b; } // definition expects ints; the second call is undefined
The return type of the function, determined by the type specifier in specifiers-and-qualifiers and possibly modified by the declarator as usual in declarations, must be a complete non-array object type or the type void
.
void f(char *s); // return type is void int sum(int a, int b); // return type of sum is int. int (*foo(const void *p))[3]; // return type is pointer to array of 3 int
The return type of a function cannot be cvr-qualified: any qualified return type is adjusted to its unqualified version for the purpose of constructing the function type: double const foo(void) { return 0.; } // declares function of type double(void) double (*foop)(void) = foo; // OK: foop is a pointer to double(void) double const (*foopc)(void) = foop; // OK: foopc is also a pointer to double(void) | (since C17) |
Function declarators can be combined with other declarators as long as they can share their type specifiers and qualifiers.
int f(void), *fip(), (*pfi)(), *ap[3]; // declares two functions and two objects inline int g(int), n; // error: inline qualifier is for functions only typedef int array_t[3]; array_t a, h(); // error: array type cannot be a return type for a function
If a function declaration appears outside of any function, the identifier it introduces has file scope and external linkage, unless static
is used or an earlier static declaration is visible. If the declaration occurs inside another function, the identifier has block scope (and also either internal or external linkage).
int main(void) { int f(int); // external linkage, file scope f(1); // definition needs to be available somewhere in the program }
The parameters in a declaration that is not part of a function definition do not need to be named:
int f(int, int); // declaration // int f(int, int) { return 7; } // Error, parameters must be named in definitions
Each parameter in a parameter-list is a declaration that introduced a single variable, with the following additional properties:
int f(int, double); // OK int g(int a, double b); // also OK int f(int, double) { return 1; } // Error: definition must name parameters
register
, and it is ignored in function declarations that are not definitions int f(static int x); // Error int f(int [static 10]); // OK (array index static is not a storage class specifier)
int f(int[]); // declares int f(int*) int g(const int[10]); // declares int g(const int*) int h(int[const volatile]); // declares int h(int * const volatile) int x(int[*]); // declares int x(int*)
int f(char g(double)); // declares int f(char (*g)(double)) int h(int(void)); // declares int h(int (*)(void))
, ...
, see variadic functions for details. int f(int, ...);
void
(but can have type pointer to void). The special parameter list that consists entirely of the keyword void
is used to declare functions that take no parameters. int f(void); // OK int g(void x); // Error
int f(size_t, uintptr_t)
is parsed as a new-style declarator for a function taking two unnamed parameters of type size_t and uintptr_t, not an old-style declarator that begins the definition of a function taking two parameters named "size_t" and "uintptr_t" See function call operator for other details on the mechanics of a function call and return for returning from functions.
Unlike in C++, the declarators f()
and f(void)
have different meaning: the declarator f(void)
is a new-style (prototype) declarator that declares a function that takes no parameters. The declarator f()
is an old-style (K&R) declarator that declares a function that takes unspecified number of parameters (unless used in an old-style function definition).
int f(void); // declaration: takes no parameters int g(); // declaration: takes unknown parameters int main(void) { f(1); // compile-time error g(2); // undefined behavior } int f(void) { return 1; ) // actual definition int g(a,b,c,d) int a,b,c,d; { return 2; } // actual definition
Unlike in a function definition, the parameter list may be inherited from a typedef.
typedef int p(int q, int r); // p is a function type int(int, int) p f; // declares int f(int, int)
In C89, specifiers-and-qualifiers was optional, and if omitted, the return type of the function defaulted to *f() { // function returning int* return NULL; } | (until C99) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/c/language/function_declaration