Names specified here
Name Description Notes Source Availability
_Noreturn Indicator of function that does not return L Q Keyword C11
inline Specifier for in-line functions L Q Keyword C99 C11
noreturn Indicator of function that does not return L M Q <stdnoreturn.h> C11
return Exit from a function L Keyword C89 C90 C95 C99 C11
void Empty return type L T Native C89 C90 C95 C99 C11
void Empty parameter list L T Native C89 C90 C95 C99 C11

The behaviour of a C program is defined by the functions from which it is built. A function is a named sequence of statements that can be executed (invoked or called) on demand. The body of a function is a block statement which is executed when the function is invoked. The function can also declare parameters, automatic variables outside of the block that are initialized on each invocation by arguments, values computed just before invoking the function. For example, here is a simple function that returns the sum of its arguments using a return statement:

int sum(int x, int y)
{
  return x + y;
}

x and y are the function's parameters, and their values are the arguments of each invocation. The braces { and } delimit the function's body. The name of the function is sum. The return statement causes the expression x + y to be evaluated, and then terminates the invocation of the function, returning the value of the expression to the caller as the result of the call. The int before the name is the return type of the function, which is the type of the result.

An invocation of the function specifies its name and the arguments in brackets, for example:

int s;

s = sum(10, 20);

sum(10, 20) is a function-call expression. Its value is the result of invoking the function with the supplied arguments, which are 10 and 20 in this example. The call expression behaves as if it is replaced with the function's body, with the parameters as local variables initialized by the supplied arguments:

int s;
{
  int x = 10;
  int y = 20;

  s = x + y;
}

The result does not have to be stored in a variable. It could be passed directly as an argument to another function call, such as printf:

#include <stdio.h>

printf("%d\m", sum(10, 20));

That would be roughly equivalent to the following:

#include <stdio.h>

{
  int x = 10;
  int y = 20;

  printf("%d\m", x + y);
}

The compiler will check that the types of the arguments match the types of the parameters. If not, arguments are converted to the correct type if possible, or it is an error.

A function can have multiple returns. The first return that is executed determines the result, and terminates the call. For example:

int absdiff(int x, int y)
{
  if (x < y)
    return y - x;

  return x - y;
}

If the first return is executed (because x is less than y), all remaining statements are ignored.

Early returns like this can sometimes cause problems for program maintenance. For example, if you want to trace the values of variables on entry to and exit from a function, you now have multiple exit points. In these cases, it is sometimes clearer to be more long-winded:

int absdiff(int x, int y)
{
  int d;
  if (x < y)
    d = y - x;
  else
    d = x - y;
  return d;
}

This form still has two exit points, but is less suggestive that one is somehow more preferred than the other:

int absdiff(int x, int y)
{
  if (x < y)
    return y - x;
  else
    return x - y;
}
int absdiff(int x, int y)
{
  return x < y ? y - x : x - y;
}

Functions without parameters

A function does not have to take any arguments. For historical reasons, this is not indicated by an empty parameter list, but by using void:

int noargexample() { . . . }     // bad
int noargexample(void) { . . . } // good

The first form is bad because it declares a function accepting unspecified arguments, so the argument-parameter check is disabled.

Functions without return values

A function does not have to return a value. The type void exists expressly for declaring functions that do not return a value:

#include <stdio.h>

void print_warning(int sec)
{
  printf("You have %d seconds remaining\n", sec);
}

When execution of the last statement in the function completes, the invocation also terminates. You can also use return to exit from the function at an earlier point:

#include <stdio.h>

void print_warning(int sec)
{
  if (sec < 1) {
    printf("Too late!\n");
    return;
  }
  printf("You have %d seconds remaining\n", sec);
}

Non-returning functions

It is occasionally useful to have a function that never returns, such as exit. From C11, you can explicitly declare that a function does not return, using the keyword _Noreturn:

_Noreturn void exit(int code)
{
  . . .
}

It is slightly more aesthetic to use the macro noreturn:

#include <stdnoreturn.h>

noreturn void exit(int code)
{
  . . .
}

noreturn allows a compiler to determine that subsequent code is at least sometimes unreachable, especially under otherwise problematic circumstances. For example:

int x;

if (test) {
  exit(0);
} else {
  x = 10;
}

printf("x = %d\n", x);

If the test is true, and exit is declared without noreturn, the compiler may reason that x has unspecified value when it is printed, and warn the programmer. With noreturn, the compiler may determine that the printf won't be reached unless x has a specified value.

If a function declared with noreturn returns, you get undefined behaviour. A good compiler will probably warn if it cannot determine that that cannot happen.

Don't use noreturn with a function that might not return. The POSIX function execve is an example that must not be declared with noreturn. If all goes well, it does not return. However, if it fails, it does return, and the caller should handle it:

if (execve("subproc", args, env) == -1) {
  perror("exec");
  exit(EXIT_FAILURE);
}
Non-returning standard functions
Name Description Notes Source Availability
exit() Terminate program (·) <stdlib.h> C89 C90 C95 C99 C11
_Exit() Terminate program without registered activity (·) <stdlib.h> C99 C11
quick_exit() Terminate program without signals (·) <stdlib.h> C11
abort() Abort program execution (·) <stdlib.h> C89 C90 C95 C99 C11
thrd_exit() Terminate the current thread (·) <threads.h> C11
longjmp() Restore execution state (·) <setjmp.h> C89 C90 C95 C99 C11

Function definitions, declarations and prototypes

When a function body is present, as in all the examples above, it is a function definition. It is the set of function definitions present in translation units constituting a program that define its behaviour. A function definition must appear exactly once in a program to be able to invoke it.

When the body is absent, and replaced by a semicolon ;, it is a function prototype. For example, here are prototypes for some of the functions we've seen so far:

int sum(int x, int y);
void print_warning(int sec);
_Noreturn void exit(int code);

Both prototype and definition serve as a function declaration.

Prototypes for the same function may appear multiple times, but must be consistent with each other and with the definition.

Parameter names in prototypes need not be the same as those given in the definition, and can be omitted. The following declarations are all consistent with earlier examples:

int sum(int, int);
void print_warning(int shoo);
_Noreturn void exit(int);

A prototype allows a function call's arguments' types to be checked against the function's parameter types. To invoke a function, a declaration for the function must be in scope. Before C99, if a function that isn't in scope is called, it is assumed to return int, and take unspecified arguments, preventing the checking their types against parameter types. From C99, it is an error to attempt to invoke a function not in scope.

There are three main places to put prototypes:

// in a header
#include "mydecls.h"

// outside all functions; visible to the rest of this file
int sum(int, int);

void myfunc(void)
{
  // within a function; visible only to the rest of this block
  int sum(int, int);

  . . .
}

A function to be called from translation units other than the one in which it is defined should be declared in a header. The header can then be included in any translation unit that needs to call it. The translation unit that defines it should also include the declaring header, to ensure that the prototype remains consistent with the definition.

In-line functions

Function calls can be expensive, and the overhead of a call can outweigh the time spent actually executing its statements. You can hint that the call should be optimized by the compiler by not actually generating a call in the translated language, but by writing the body of the function in place of the call. The declaration of the function must now include the body and the keyword inline:

// an in-line declaration
inline int sum(int x, int y)
{
  return x + y;
}

To be used in mutliple translation units, the declaration including the body must appear in a header, and a definition must be provided in one of the translation units. The definition must be what appears to be a prototype, explicitly using the normally redundant keyword extern:

// an in-line definition
extern int sum(int x, int y);

Function-definition syntax

external-declaration
function-definition
declaration
function-definition
declaration-specifiers declarator compound-statement
declaration-specifiers declarator declaration-list compound-statement
The pre-standard way
declaration-specifiers
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
function-specifier declaration-specifiersopt
alignment-specifier declaration-specifiersopt
function-specifier
inline
_Noreturn
declarator
pointeropt direct-declarator
direct-declarator
direct-declarator ( parameter-type-list )
direct-declarator ( identifier-listopt )
The pre-standard way
parameter-type-list
parameter-list
parameter-list , ...
parameter-list
parameter-declaration
parameter-list , parameter-declaration
parameter-declaration
declaration-specifiers declarator
declaration-specifiers abstract-declaratoropt
jump-statement
return expressionopt ;

Function-call syntax

postfix-expression
postfix-expression ( argument-expression-listopt )
Function calls
argument-expression-list
assignment-expression
argument-expression-list , assignment-expression

CHaR
Sitemap Supported
Site format updated 2024-06-05T22:37:07.391+0000
Data updated 1970-01-01T00:00:00.000+0000
Page updated 2022-06-17T21:43:05.000+0000