Functions

Functions should generally only ever be declared at file-scope; these are also called external declarations, because they appear outside of any enclosing scope–not to be confused with external linkage.

Definitions

A function definition takes the form of a declaration of a function, followed by a function body enclosed in curly braces; for example,

int sum(int a, int b)
{
   return a + b;
}

This defines the function sum with external linkage, so that it may be accessed in other translation units (source files). The extern specifier may be used to explicitly denote external linkage, but is otherwise redundant. To define an internally linked function, use the storage class specifier static,

static int sum(int a, int b)
{
   return a + b;
}

Externally linked functions represent the interface of a program or library. Thus, the main() function must be externally linked so that it can be called by the C runtime when a program is executed. Otherwise, functions should generally be declared static unless their identifiers are to be exported as part of an API, such as when writing a library.

Declarations

Functions may also be declared without providing a definition. This is required before calling an externally linked function defined in another translation unit, and can also be used to break cyclic dependencies and organize code internally.

A function may be prototyped, where the types of its parameters are fully specified. The parameter names are optional, as in int sum(int, int);, but they should be included for clarity, int sum(int a, int b);. A prototyped function may be called directly,

int sum(int a, int b); /* defined in another translation unit */

int main()
{
   return sum(1, 2); /* 3 */
}

Internally linked functions may also be prototyped; this is necessary to resolve certain circular dependencies but is also frequently used to organize code. In the example below, the prototype for is_even before the definition of is_odd breaks the circular dependency between the two function definitions,

static int is_even(int x);

static int is_odd(int x)
{
   if (x == 1) return 1;
   else return is_even(x - 1);
}

static int is_even(int x)
{
   if (x == 0) return 1;
   else return is_odd(x - 1);
}

As a special case the parameter list for a function prototype that has no parameters must be specified void, as in int f(void); rather than int f();. This is because the latter declaration is not a prototype, and instead forward declares a function that takes unspecified arguments, rather than none.

int f(); /* Forward declaration--unspecified parameters. Avoid! */
int g(void); /* Prototype--no parameters */

int main()
{
   f();        /* Ok */
   f(1, 2, 3); /* Ok, argument types are deduced (deprecated) */

   g();        /* Ok */
   g(1, 2, 3); /* Error */
}

As outlined in the style guide, it is a good practice to organize programs so that all functions used in the program are prototyped before the definition of main(), with all function definitions after main(),

int atoi(char *s); /* library method to convert string to integer */

static int is_even(int x);
static int is_odd(int x);

int main(int argc, char *argv[])
{
   if (argc > 1) return is_even(atoi(argv[1]));
   else return -1;
}

static int is_odd(int x)
{
   if (x == 1) return 1;
   else return is_even(x - 1);
}

static int is_even(int x)
{
   if (x == 0) return 1;
   else return is_odd(x - 1);
}