Function Definitions

 

 

A function definition (either prototype or nonprototype) contains the following:

A nonprototype function definition can also have a list of parameter declarations, which describe the types of parameters that the function receives. In nonprototype functions, parameters that are not declared have type int.

A function can be called by itself or by other functions. Unless a function definition has the storage class specifier static, the function also can be called by functions that appear in other files or modules. Functions with a storage class specifier of static can only be directly invoked from within the same source file.

If a function has the storage class specifier static or a return type other than int, the function definition or a declaration for the function must appear before, and in the same file as, a call to the function. If a function definition has external linkage and a return type of int, calls to the function can be made before it is visible because an implicit declaration of extern int func(); is assumed.

All declarations for a given function must be compatible; that is, the return type is the same and the parameters have the same type.

The default type for the return value and parameters of a function is int, and the default storage class specifier is extern. If the function does not return a value or it is not passed any parameters, use the keyword void as the type specifier.

You can include ellipses (...) at the end of your parameter list to indicate that a variable number of arguments will be passed to the function. Parameter promotions are performed, and no type checking is done.

A function cannot have a return type of function, array, or, in C, any type having the volatile or const qualifier. However, a function can return a pointer or reference to a function, array, or to an object with a volatile or const type.

In C, you cannot declare a function as a struct or union member.

You cannot define an array of functions. You can, however, define an array of pointers to functions.

Function Declarator
The function declarator shown in the function definition syntax diagram names the function and lists the function parameters. It contains an identifier that names the function and a list of the function parameters. You should always use prototype function declarators because of the parameter checking that can be performed. The detailed syntax structure for the function declarator is:

where:

parameter_declaration_list
abstract_declarator

Prototype Function Declarators
Each parameter should be declared within the function declarator. Any calls to the function must pass the same number of arguments as there are parameters in the declaration.

Nonprototype Function Declarators
Each parameter should be declared in a parameter declaration list following the declarator. If a parameter is not declared, it has type int.

char and short parameters are widened to int, and float to double. No type checking between the argument type and the parameter type is done for nonprototyped functions. As well, there are no checks to ensure that the number of arguments matches the number of parameters.

Each value that a function receives should be declared in a parameter declaration list for nonprototype function definitions that follows the declarator.

A parameter declaration determines the storage class specifier and the data type of the value.

The only storage class specifier allowed is the register storage class specifier. Any type specifier for a parameter is allowed. If you do not specify the register storage class specifier, the parameter will have the auto storage class specifier. If you omit the type specifier and you are not using the prototype form to define the function, the parameter will have type int.

int func(i,j)
{
   /*  i and j have type int  */
}

You cannot declare a parameter in the parameter declaration list if it is not listed within the declarator.

Ellipsis and void
An ellipsis at the end of a parameter declaration indicates that the number of arguments is equal to, or greater than, the number of specified argument types. At least one parameter declaration must come before the ellipsis. Where it is permitted, an ellipsis preceded by a comma is equal to a simple ellipsis.

int f(int,...);

The comma before the ellipsis is optional.

Parameter promotions are performed as needed, but no type checking is done on the variable arguments.

You can declare a function with no arguments in two ways:

int f(void);    /* f() takes no parameters    */
int f();        /* f() takes any number       */
                /* or type or parameters      */

An empty argument declaration list or the argument declaration list of (void) indicates a function that takes no arguments. void cannot be used as an argument type, although types derived from void (such as pointers to void) can be used.

In the following example, the function f() takes one integer parameter and returns no value, while g() expects no parameters and returns an integer.

void f(int)
int g(void)

Function Body
The body of a function is a block statement.

The following function body contains a definition for the integer variable big_num, an if-else control statement, and a call to the function printf:

void largest(int num1, int num2)
{
   int big_num;

   if (num1 >= num2)
      big_num = num1;
   else
      big_num = num2;

   printf("big_num = %d\n", big_num);
}


Functions
Function Calls


Example of the main() Function
Examples of Function Declarations
Examples of Function Definitions


main() Function
Function Declarations