Function definitions - cppreference.com

From cppreference.com

A function definition associates the function body (a sequence of declarations and statements) with the function name and parameter list. Unlike

function declaration

, function definitions are allowed at file scope only (there are no nested functions).

C supports two different forms of function definitions:

attr-spec-seq(optional)specifiers-and-qualifiersparameter-list-declaratorfunction-body(1) specifiers-and-qualifiersidentifier-list-declaratordeclaration-listfunction-body(2) (until C23)where

attr-spec-seq- (C23)an optional list of

attributes

, applied to the function specifiers-and-qualifiers- a combination of

type specifiers

that, possibly modified by the declarator, form the return type

storage class specifiers

, which determine the linkage of the identifier (static, extern, or none)

function specifiers

inline

,

_Noreturn

, or none

parameter-list-declarator- a declarator for a function type which uses a

parameter list

to designate function parameters identifier-list-declarator- a declarator for a function type which uses a

identifier list

to designate function parameters declaration-list- sequence of declarations that declare every identifier in identifier-list-declarator. These declarations cannot use initializers and the only

storage-class specifier

allowed is register. function-body- a

compound statement

, that is a brace-enclosed sequence of declarations and statements, that is executed whenever this function is called 1) New-style (C89) function definition. This definition both introduces the function itself and serves as a function prototype for any future

function call expressions

, forcing conversions from argument expressions to the declared parameter types.

intmax(inta,intb){returna>b?a:b;}doubleg(void){return0.1;}2)(until C23) Old-style (K&R) function definition. This definition does not behave as a prototype and any future

function call expressions

will perform default argument promotions.

intmax(a,b)inta,b;{returna>b?a:b;}doubleg(){return0.1;}Explanation

As with

function declarations

, 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. If the return type would be cvr-qualified, it is adjusted to its unqualified version for the purpose of constructing the function type.

voidf(char*s){puts(s);}// return type is voidintsum(inta,intb){returna+b;}// return type is intint(*foo(constvoid*p))[3]{// return type is pointer to array of 3 intreturnmalloc(sizeof(int[3]));}As with

function declarations

, the types of the parameters are adjusted from functions to pointers and from arrays to pointers for the purpose of constructing the function type and the top-level cvr-qualifiers of all parameter types are ignored for the purpose of determining

compatible function type

.

Unlike

function declarations

, unnamed formal parameters are not allowed (otherwise, there would be conflicts in old-style (K&R) function definitions), they must be named even if they are not used within the function. The only exception is the special parameter list (void).

(until C23)Formal parameters may be unnamed in function definitions, because old-style (K&R) function definitions has been removed. Unnamed parameters are inaccessible by name within the function body.

(since C23)intf(int,int);// declaration// int f(int, int) { return 7; } // Error until C23, OK since C23intf(inta,intb){return7;}// definitionintg(void){return8;}// OK: void doesn't declare a parameterWithin the function body, every named parameter is an

lvalue

expression, they have automatic

storage duration

and

block scope

. The layout of the parameters in memory (or if they are stored in memory at all) is unspecified: it is a part of the

calling convention

.

intmain(intac,char**av){ac=2;// parameters are lvaluesav=(char*[]){"abc","def",NULL};f(ac,av);}See

function call operator

for other details on the mechanics of a function call and

return

for returning from functions.

__func__

Within every function-body, the special predefined variable __func__ with block scope and static storage duration is available, as if defined immediately after the opening brace by

staticconstchar__func__[]="function name";This special identifier is sometimes used in combination with the

predefined macro constants

__FILE__ and __LINE__, for example, by

assert

.

(since C99)Notes

The argument list must be explicitly present in the declarator, it cannot be inherited from a typedef

typedefintp(intq,intr);// p is a function type int(int, int)pf{returnq+r;}// ErrorIn C89, specifiers-and-qualifiers was optional, and if omitted, the return type of the function defaulted to int (possibly amended by the declarator).

In addition, old-style definition didn't require a declaration for every parameter in declaration-list. Any parameter whose declaration was missing had type int

max(a,b)// a and b have type int, return type is int{returna>b?a:b;}(until C99)Defect reports

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 References

C17 standard (ISO/IEC 9899:2018):

6.9.1 Function definitions (p: 113-115)

C11 standard (ISO/IEC 9899:2011):

6.9.1 Function definitions (p: 156-158)

C99 standard (ISO/IEC 9899:1999):

6.9.1 Function definitions (p: 141-143)

C89/C90 standard (ISO/IEC 9899:1990):

3.7.1 Function definitions

See also