C Functions & Prototypes Tutorial

In this C tutorial we learn how to functions allow us to group multiple statements together for reuse in our program.

We cover how to define a function and prototype, how to use (call) a function, how to accept parameters and how to return a value from a function.

What is a function

A function is a way for a developer to group one or more statements together for reuse throughout our code.

So far in the course, any functionality we wanted in our program was done inside the Main() function. But, when an application becomes bigger and more complex, we need to separate our code into smaller sections of logic.

Ideally we want one section of code to only be responsible for one task, and be repeatable, so we separate the sections into functions.

As an example, let’s consider some simple functionality.

Example:
#include <stdio.h>

int main()
{
    // number to check
    int num = 5;

    // if the number can be divided by two
    // without a remainder, it's an even num
    if (num % 2 == 0)
        printf("%d is an even number\n", num);
    else
        printf("%d is an odd number\n", num);

    return 0;
}

In the example above we check if a number is an odd or even number by evaluating if the number can be divided by 2.

If it can be divided by two without a remainder, the number is even, otherwise the number is an odd number.

We can separate this logic into a function to allow it to be reusable.

How to define a function

A function in C is defined in two stages.

  1. First, we use a prototype of the function to tell the compiler that a function with a similar name and structure might be used in the code later on.
  2. Second, we define the actual function with the same name and basic structure as the prototype, but this time with a body that contains some logic.

We can look at a function definition first, because a prototype is simply the structure of the same function.

A function definition in C consists of the following:

  • A return type.
  • A name.
  • A list of input parameters (optional).
  • At least one statement in it’s body.
  • An returned value (optional).
Syntax:
returnType name(parameters)
{
    // logic statements
    returnedValue
}

We’ll start by defining a barebones function, and add features as we need them.

First, we need a return type. A function can return a value from its body of logic if we want it to. For that reason we need to specify what type of value will come from it with the return type.

We learned from the data types tutorial that a special void type exists in C for situations where we don’t want to return anything. The void type simply uses the void keyword.

Example:
void name(parameters)
{
    // logic statements
    returnedValue
}

Next, we need a name for our function. The name will be used to identify the function when we need to use it.

Example:
void myFunction(parameters)
{
    // logic statements
    returnedValue
}

We don’t have to specify any function parameters if we don’t need them, so we can leave the parameter list blank.

However, the open and close parentheses must always be written in the prototype, the definition and when we use the function.

Example:
void myFunction()
{
    // logic statements
    returnedValue
}

A function needs at least one statement inside it’s code block, commonly referred to as the function body. If a function doesn’t do anything, it doesn’t need to exist.

Example:
void myFunction()
{
    printf("Hello from inside a function\n");

    returnedValue
}

A function doesn’t need to return a value, and because we already stated it won’t return a value (with the void keyword), we can remove the return statement.

Example:
void myFunction()
{
    printf("Hello from inside a function\n");
}

The example above, is the most barebones function that we can define. Let’s see what it will look like in our program.

Example:
#include <stdio.h>

int main()
{
    return 0;
}

void myFunction()
{
    printf("Hello from inside a function\n");
}

In the example above, we defined our myFunction() outside the body of the main() function.

As mentioned earlier, we need to tell the compiler that this function might be used somewhere in the code. We do this with a function prototype.

The function prototype looks exactly like the function definition, except it doesn’t include the body.

Example:
#include <stdio.h>

void myFunction(); // prototype

int main()
{
    return 0;
}

void myFunction()
{
    printf("Hello from inside a function\n");
}

In the example above, we define a prototype of our function at the top of the document, after any includes.

It has the same return type, name and parameters that our function has but instead of a body, the prototype statement is terminated with a semicolon.

At this point we’ve created our own custom function. However, if we run the example, nothing happens. That’s because we’ve only defined the function, we didn’t use it yet.

How to use (call) a function

To use a function, we have to call it somewhere in our code. The syntax to call a function looks the same as the prototype, except it doesn’t include the return type.

Syntax:
// prototype
returnType name(parameters);

// call
name(arguments);

To call a function we write its name, followed by parentheses. Between the parentheses we write any arguments for the parameters, if there are any.

Let’s call our simple function from the definition section.

Example:
#include <stdio.h>

// prototype
void myFunction();

int main()
{
    // call
    myFunction();

    return 0;
}

// definition
void myFunction()
{
    printf("Hello from inside a function\n");
}

This time, when we run the program, we see the message from our function printed to the console.

How to accept parameters in a function

Parameters act as inputs for our function. The function can use those inputs inside its execution block.

Syntax:
// prototype
returnType name(paramType paramName);

// definition
returnType name(paramType paramName)
{
    // use paramName
}

A parameter is a variable declaration inside the parentheses of the function. When a parameter has been declared, we can use it inside, and only inside, the function body.

Both the prototype, and the definition must include the parameters for the function.

Example:
#include <stdio.h>

void myFunction(char message[]);

int main()
{
    return 0;
}

void myFunction(char message[])
{
    printf(message);
}

In the example above we declare a char array called message as a parameter. In the function body we use the message parameter inside the printf() statement.

When the function is called, anything that we write between the parentheses will replace any instances of message inside the function body.

This time, when we call the function, we have to specify an argument between the parentheses.

Example:
#include <stdio.h>

void function(char message[]);

int main()
{
    function("Hello from a parameter\n");

    return 0;
}

void function(char message[])
{
    printf(message);
}

When we run the example above, the string we passed as an argument in the function call is printed to the console.

If we want to supply more than one parameter, we separate them with a comma.

Example:
#include <stdio.h>

void function(char msg1[], char msg2[]);

int main()
{
    function("Hello", "World");

    return 0;
}

void function(char msg1[], char msg2[])
{
    printf(msg1);
    printf(" ");
    printf(msg2);
    printf("\n");
}

How to return a value from a function

As mentioned before, a value can be returned from a function. We can then choose to store that returned value into a data container like a variable, or use it directly.

To return a value from a function, we write the keyword return , followed by the value we want to return.

Syntax:
returnType name(parameters)
{
    // logic statements
    return valueToReturn;
}
Example:
#include <stdio.h>

// prototype
int sumOf(int a, int b);

int main()
{
    // call
    sumOf(5, 3);

    return 0;
}

// definition
int sumOf(int a, int b)
{
    return a + b;
}

In the example above, our function takes in two integers, adds them together and returns them out from the function. But, when we run the function, nothing happens. We returned a value, but we didn’t do anything with it.

We can store this value into a variable, or use it directly.

Example:
#include <stdio.h>

int sumOf(int a, int b);

int main()
{
    // stored and then used
    int result = sumOf(5, 3);
    printf("Result: %d\n", result);

    // used directly
    printf("sumOf: %d\n", sumOf(2, 3));

    return 0;
}

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

In the example above, our first function call stored the return value into a variable. We can use this variable elsewhere in our program and in this case we print it to the console on the next line.

Our second call of the function is directly within the printf() statement. In this case we won’t be able to do anything else with the result, it will only be used in this one instance.

Custom isEven() function

At this point we’ve learned enough about functions in C, to be able to convert the functionality at the start of this tutorial into our own custom function.

As a small challenge, try to convert the functionality below into a function. If you get stuck, see our solution.

Functionality:
#include <stdio.h>

int main()
{
    // number to check
    int num = 5;

    // if the number can be divided by two
    // without a remainder, it's an even num
    if (num % 2 == 0)
        printf("%d is an even number\n", num);
    else
        printf("%d is an odd number\n", num);

    return 0;
}
Possible Solution:
#include <stdio.h>

int isEven(int num);

int main()
{
    isEven(3);
    isEven(6);
    isEven(19);
    isEven(-38);
    isEven(77);
    isEven(10458);
    isEven(-89620);

    return 0;
}

int isEven(int num)
{
    if (num % 2 == 0)
        printf("%d is an even number\n", num);
    else
        printf("%d is an odd number\n", num);
}

Summary: Points to remember

  • A function is used to group statements together for code reuse.
  • Any function that’s defined needs to have a corresponding prototype.
  • Defining a function and prototype is not enough, we need to call a function somewhere in our code to use it.
  • A function can accept input parameters which can then be used inside the function.
  • We can return a value from a function that is of the same type we specify as the function return type.