A function declaration introduces anidentifier that designates a function and, optionally, specifies the types of the function parameters (theprototype). Function declarations (unlikedefinitions) may appear at block scope as well as file scope.
Contents |
In thedeclaration grammar of a function declaration, thetype-specifier sequence, possibly modified by the declarator, designates thereturn type (which may be any type other than array or function type), and thedeclarator has one ofthree(until C23)two(since C23) forms:
noptr-declarator( parameter-list) attr-spec-seq(optional) | (1) | ||||||||
noptr-declarator( identifier-list) attr-spec-seq(optional) | (2) | (until C23) | |||||||
noptr-declarator( ) attr-spec-seq(optional) | (3) | ||||||||
where
noptr-declarator | - | anydeclarator 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 keywordvoid or a comma-separated list ofparameters, which may end with anellipsis parameter |
identifier-list | - | comma-separated list of identifiers, only possible if this declarator is used as part of old-stylefunction definition |
attr-spec-seq | - | (C23) an optional list ofattributes, applied to the function type |
int max(int a,int b);// declarationint n= max(12.01,3.14);// OK, conversion from double to int
int max(a, b)int a, b;// definition expects ints; the second call is undefined{return a> b? a: b;} 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)
The return type of the function, determined by the type specifier inspecifiers-and-qualifiers and possibly modified by thedeclarator as usual indeclarations, must be a non-array object type or the typevoid. If the function declaration is not a definition, the return type can beincomplete. The return type cannot be cvr-qualified: any qualified return type is adjusted to its unqualified version for the purpose of constructing the function type.
void f(char*s);// return type is voidint sum(int a,int b);// return type of sum is int.int(*foo(constvoid*p))[3];// return type is pointer to array of 3 int doubleconst bar(void);// declares function of type double(void)double(*barp)(void)= bar;// OK: barp is a pointer to double(void)doubleconst(*barpc)(void)= barp;// OK: barpc is also a pointer to double(void)
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 objectsinlineint g(int), n;// Error: inline qualifier is for functions onlytypedefint 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 hasfile scope andexternal linkage, unlessstatic 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, block scope f(1);// definition needs to be available somewhere in the program}
The parameters in a declarationthat is not part of afunction definition(until C23) do not need to be named:
int f(int,int);// declaration// int f(int, int) { return 7; } // Error: parameters must be named in definitions// This definition is allowed since C23
Each parameter in aparameter-list is adeclaration that introduced a single variable, with the following additional properties:
int f(int,double);// OKint g(int a,double b);// also OK// int f(int, double) { return 1; } // Error: definition must name parameters// This definition is allowed since C23
int f(staticint x);// Errorint f(int[static10]);// OK (array index static is not a storage class specifier)
int f(int[]);// declares int f(int*)int g(constint[10]);// declares int g(const int*)int h(int[constvolatile]);// 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))
, ...
or be...
(since C23), seevariadic functions for details.int f(int, ...);
int f(void);// OKint g(void x);// Error
Attribute specifier sequences can also applied to function parameters. | (since C23) |
Seefunction call operator for other details on the mechanics of a function call andreturn for returning from functions.
Unlike in C++, the declaratorsf() andf(void) have different meaning: the declaratorf(void) is a new-style (prototype) declarator that declares a function that takes no parameters. The declaratorf() is a declarator that declares a function that takesunspecified number of parameters (unless used in a function definition) int f(void);// declaration: takes no parametersint g();// declaration: takes unknown parameters int main(void){ f(1);// compile-time error g(2);// undefined behavior} int f(void){return1;}// actual definitionint g(a,b,c,d)int a,b,c,d;{return2;}// actual definition | (until C23) |
Unlike in afunction definition, the parameter list may be inherited from a typedef
typedefint 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 toint (possibly amended by thedeclarator). *f(){// function returning int*returnNULL;} | (until C99) |
The following behavior-changing defect reports were applied retroactively to previously published C standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
DR 423 | C89 | the return type might be qualified | the return type is implicitly disqualified |
C++ documentation forFunction declaration |