Sage-Code Laboratory
index<--

C Functions

A function is defined as a relation between input parameters and output results. In mathematics a function should be deterministic. Unique input will produce same result. If this is not true than the function is stochastic.

What is a function?

The idea of function comes from mathematics but in IT sometimes a function can be just another synonym for sub-routine. A sub-routine is a set of statements encapsulated into a block of code with a name. Sub-routines can have input/output parameters and one or multiple results.

The role of a sub-routine is covered by functions. C do not have a reserved keyword to declare a function. In other languages we have "fn" or "def" or "func" but in C like in Java you specify the name of the function and the result type. So a function in C is not actually a function but a "named section" of code.

function

Function Concepts

Declare Function

We declare functions in C using a minimalist syntax. We start declaration with the returning type followed by function identifier (name). After the function name we can specify a list of parameters. Parameter names are separated by comma and enclosed in round parenthesis. After the parameter list we open brackets and create the function block.

Syntax Pattern

//define a function
type function_name(type p1 = value, type p2 = value ...) {
    //function block (with statements)
    ...
    return expression;
}

//call function from main function
int main() {
    type x = function_name(1, 2);
}

Function Scope

A function have a local scope. That means you can define variables that exist only inside the function body. After function is ending the local scope is cleared. All variables defined in local scope will be removed from memory.

In contrast to local scope, every C program unit has a global scope. If you define variables outside of any function these variables are visible in all functions, except if you define other local variable with the same name. In this case the global variable can be shadowed by the local variable.

I the function main() defined above you can see local variables: x, y, r and op. Also x =10, y=10 global variables are defined, except these two are unused and have no effect over the computations.

Side Effects

Functions that can read from console, print something or modify global variables. These actions are called side-effects. In example above, function main() has side-effects but function add() and sub() are pure. Do not have side-effects.

Parameters

Functions can receive one or more parameters. These are sometimes called "formal parameters". Parameters are similar to local variables, except they do not have initial value. The value for the parameter is establish in the function call.

In the example above, functions add() and sub() have each 2 parameters: a, b. List of parameters is separated by comma. For each parameter you must declare data type and provide a "actual value" that is called argument.

Note: C do not have default parameters. Next examples are invalid declarations attempts in C:

 // invalid declaration
int add (int a = 0, int b = 0) {
 return (a + b);
}
// invalid declaration
int sub (int a, b) {
 return (a + b);
}

Return Result

A function can use return keyword to create the result. Observe that result type is declared in function definition. It is the first thing before the function identifier. So the compiler will know if your expression used by return will create the right type.

Syntax:

return <expression>;

Where <expression> can be a formula, or a constant literal. If the function do not have return then the function is void. For declaring a void function we use special keyword: void. This has significance of a type that has no value.

Example:

void main() {
 ; //empty statement
}

The above example does nothing at all but will terminate with error. Usually a C program uses int main() function and return a number that can be 0 or !=0. If the code is not 0 it means the program has an error defined probably by the error code.

Example:

int main() {
 return 0; //success
}

Function Call

To call a function you must use function name follow by a list of arguments enclosed in parentheses (). If the function has a result then it can be used in expressions. Also function result name can be ignored.

Example:

#include <stdio.h>
    // no result
    void add1(int a, int b) {
        printf("ad1 = %d\n",a+b);
    };
    // has int result
    int add2(int a, int b) {
        return a+b;
    };

    void fn_test() {
        int x;
        /* call function add1 */
        add1(1,2); //print 1+1 = 2
        /* call function add2 */
        add2(1,2); //result is ignored
        /* call function add2 in expression */
        int r = add2(1,2);
        printf("ad2 = %d\n",r);
    }

Output parameters

This is a cool feature of functions. It enable you to modify parameter values inside the function body and propagate the new value back to the calling program. This technique can be used for functions to return more than one value. You can do this by using pointers as function parameters.

Example:

#include <stdio.h>
void swap(int *x, int *y) {
    register int t; //temporary value
    t = *y; *y = *x; *x = t;
}
int main () {
    int a = 1, b = 2;
    printf("a = %d b = %d \n",a,b);
    swap(&a, &b); //function call
    printf("a = %d b = %d \n", a, b);
    return 0;
}

Registry Variables

There is a class of special variables called register variables. These are local variables that should be stored in a CPU registry instead of RAM. For this variable we can’t use operator ‘&’ to read memory location. Therefore we can’t have a pointer to a register variables.

{
 register int x;
}

The registry variables can be used for very fast access. It may be for example a counter. The compiler will try to create this kind of variable on registry but is not 100% guaranteed it will be. 

Multiple results

A function can have a single result. This result is created with return keyword. Sometimes we need more then one results from a function. In this case we need to define a composite type and use this type as result. Another method to make a function compute multiple results is to use output parameters or to use global variables and side-effects.

Probably you will not understand above examples, be patient and read next articles. After you understand better the composite types and pointers you will be able to create such functions yourself.

Static Variables

Example:

#include <stdio.h>
#include <stdlib.h>

/* goal parameters */
int start = 5;
int stop  = 10;

/* a generator function */
int next()
{
    static int c = 0;
    if (c == 0) {
        c = start;
        c++;
    } else
        c++;
    return c;
}

int main () {
    int i = 0;
    i = start;

    while (i <= stop) {
       printf("%d,", i);
       i = next();
    }
    return 0;
}

Note: In previous example we have used keyword: "static" to define a special kind of variable. This variable is defined only once, and it exists during program execution. When the function is called this variable will not be re-defined. Therefore will not have value 0 second time it is called but a different value.

REPL Application

Next will create a complex example that is very common. It is call Read Execute Print Loop (REPL). It may be used to evaluate expressions or even as Command Line Interface (CLI) kind of application.

In every C program you must create function main(). If this function is missing the program can not compile. Function main() will drive the program. Usual this function contains a loop that is called the main loop.

Inside the main loop you can display a menu, ask for user input, call other functions, perform computations, display the results and exit. This is the most common structure of a program:

repl

REPL Diagram


Example:

#include <stdio.h>
#include <stdlib.h>
//global variables
int x = 10, y = 10;

//user defined function add()
int add (int a, int b) {
    return (a + b);
}

//user defined function sub()
int sub (int a, int b) {
    return (a - b);
}
//driver function main
int main () {
    //local variables
    int x = 0, y = 0, r = 0;
    char op;

    //begin loop
    do {
        op = '_';
        printf("CALCULATOR\n");
        printf("enter two numbers ...\n");
        printf("enter value for x:");
        scanf("%i",&x);
        printf("enter value for y:");
        scanf("%i",&y);
        printf("operation (+, -) or (.) to exit:");
        operation: // label for goto
        op = getchar();

        //make the selection
        switch (op) {
            case '+':
                r = add(x,y); //function call
                break;
            case '-':
                r = sub(x,y); //function call
                break;
            case '.':
                printf("goodbye!\n");
                break;
            default:
                goto operation; //read the operation again
        }
        if (op !='.') {
            printf("\n %i %c %i = %i \n",x,op,y,r);
            printf("press any key to continue...\n");
            getchar()
        }
    } while (op != '.'); //end loop
    return 0;
}

Read next: Control Flow