Functions

Functions are central to C programming. Functions are usually defined as subprograms which return a value based on a number of input parameters. Return value of the function can be used in expressions – technically, function call is considered to be an expression like any other.

C allows a function to create results other than its return value, referred to as side effects. Often, the function return value is not used at all, depending on the side effects. These functions are equivalent to procedures of other programming languages, such as Pascal. C does not distinguish between procedure and function – functions play both roles.

Each program must have a single external function named main marking the entry point of the program. Functions are usually declared as prototypes in standard or user-supplied header files, or within program files. Functions have external linkage by default and are normally accessible from any file in the program. This can be restricted by using the static storage class specifier in function declaration (see Storage Classes and Linkage).

  Note : Check the PIC32 Specifics for more information on functions’ limitations on the PIC32 MCUs.

Function Declaration

Functions are declared in user's source files or made available by linking precompiled libraries. The declaration syntax of the function is:

type function_name(parameter-declarator-list);

The function_name must be a valid identifier. This name is used to call the function; see Function Calls for more information.

type represents the type of function result, and can be of any standard or user-defined type. For functions that do not return value the void type should be used. The type can be omitted in global function declarations, and function will assume the int type by default.

Function type can also be a pointer. For example, float* means that a function result is a pointer to float. The generic pointer void* is also allowed.

The function cannot return an array or another function.

Within parentheses, parameter-declarator-list is a list of formal arguments that function takes. These declarators specify the type of each function parameter. The compiler uses this information to check validity of function calls. If the list is empty, a function does not take any arguments. Also, if the list is void, a function also does not take any arguments; note that this is the only case when void can be used as an argument’s type.

Unlike variable declaration, each argument in the list needs its own type specifier and possible qualifier const or volatile.

Function Prototypes

A function can be defined only once in the program, but can be declared several times, assuming that the declarations are compatible. When declaring a function, the formal argument's identifier does not have to be specified, but its type does.

This kind of declaration, commonly known as the function prototype, allows better control over argument number, type checking and type conversions. The name of a parameter in function prototype has its scope limited to the prototype. This allows one parameter identifier to have different name in different declarations of the same function:

/* Here are two prototypes of the same function: */

int test(const char*)   /* declares function test */
int test(const char*p)  /* declares the same function test */

Function prototypes are very useful in documenting code. For example, the function Cf_Init takes two parameters: Control Port and Data Port. The question is, which is which? The function prototype:

void Cf_Init(char *ctrlport, char *dataport);

makes it clear. If a header file contains function prototypes, the user can read that file to get the information needed for writing programs that call these functions. If a prototype parameter includes an identifier, then the indentifier is only used for error checking.

Function Definition

Function definition consists of its declaration and function body. The function body is technically a block – a sequence of local definitions and statements enclosed within braces {}. All variables declared within function body are local to the function, i.e. they have function scope.

The function itself can be defined only within the file scope, which means that function declarations cannot be nested.

To return the function result, use the return statement. The statement return in functions of the void type cannot have a parameter – in fact, the return statement can be omitted altogether if it is the last statement in the function body.

Here is a sample function definition:

/* function max returns greater one of its 2 arguments: */

int max(int x, int y) {
  return (x>=y) ? x : y;
}

Here is a sample function which depends on side effects rather than return value:

/* function converts Descartes coordinates (x,y) to polar (r,fi): */
#include <math.h>

void polar(double x, double y, double *r, double *fi) {
  *r = sqrt(x * x + y * y);
  *fi = (x == 0 && y == 0) ? 0 : atan2(y, x);
  return; /* this line can be omitted */
}

Functions reentrancy

Functions reentrancy is allowed. Remember that the PIC32 has stack and memory limitations which can varies greatly between MCUs.

Copyright (c) 2002-2012 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!
Want more examples and libraries? 
Find them on LibStock - A place for the code