# C Programming/Procedures and functions

In C programming, all executable code resides within a **function**.
Note that other programming languages may distinguish between a
\"function\", \"subroutine\", \"subprogram\", \"procedure\", or
\"method\" \-- in C, these are all functions. Functions are a
fundamental feature of any high level programming language and make it
possible to tackle large, complicated tasks by breaking tasks into
smaller, more manageable pieces of code.

At a lower level, a function is nothing more than a memory address where
the instructions associated with a function reside in your computer\'s
memory. In the source code, this memory address is usually given a
descriptive name which programmers can use to **call** the function and
execute the instructions that begin at the function\'s starting address.
The instructions associated with a function are frequently referred to
as a **block** of code. After the function\'s instructions finish
executing, the function can return a value and code execution will
resume with the instruction that immediately follows the initial call to
the function. If this doesn\'t make immediate sense to you, don\'t
worry. Understanding what is happening inside your computer at the
lowest levels can be confusing at first, but will eventually become very
intuitive as you develop your C programming skills.

For now, it\'s enough to know that a function and its associated block
of code is often executed (called) several times, from several different
places, during a single execution of a program.

As a basic example, suppose you are writing a program that calculates
the distance of a given (x,y) point to the x-axis and to the y-axis. You
will need to compute the absolute value of the whole numbers x and y. We
could write it like this (assuming we don\'t have a predefined function
for absolute value in any library):

``` c
#include <stdio.h>

/*this function computes the absolute value of a whole number.*/
int abs(int x)
{
        if (x>=0) return x;
        else return -x;
}

/*this program calls the abs() function defined above twice.*/
int main()
{
        int x, y;
        
        printf("Type the coordinates of a point in 2-plane, say P = (x,y). First x=");
        scanf("%d", &x);
        printf("Second y=");
        scanf("%d", &y);
        
        printf("The distance of the P point to the x-axis is %d. \n Its distance to the y-axis is %d. \n", abs(y), abs(x));

        return 0;
}
```

The next example illustrates the usage of a function as a procedure.
It\'s a simplistic program that asks students for their grade for three
different courses and tells them if they passed a course. Here, we
created a function, called `check()` that can be called as many times as
we need to. The function saves us from having to write the same set of
instructions for each class the student has taken.

``` c
#include<stdio.h>

/*the 'check' function is defined here.*/
void check(int x)
{
        if (x<60)
                printf("Sorry! You will need to try this course again.\n");
        else
                printf("Enjoy your vacation! You have passed.\n");
}

/*the program starts here at the main() function, which calls the check() function three times.*/
int main()
{
        int a, b, c;
        
        printf("Type your grade in Mathematics (whole number). \n");
        scanf("%d", &a);
        check(a);
        
        printf("Type your grade in Science (whole number). \n");
        scanf("%d", &b);
        check(b);
        
        printf("Type your grade in Programming (whole number). \n");
        scanf("%d", &c);
        check(c);

        /* this program should be replaced by something more meaningful.*/
        return 0;
}
```

Notice that in the program above, there is no outcome value for the
\'check\' function. It only executes a procedure.

This is precisely what functions are for.

## More on functions

It\'s useful to conceptualize a function like a machine in a factory. On
the input side of the machine, you dump in the \"raw materials,\" or the
input data, that you want the machine to process. Then the machine goes
to work and and spits out a finished product, the \"return value,\" to
the output side of the machine which you can collect and use for other
purposes.

In C, you must tell the machine exactly what raw materials it is
expected to process and what kind of finished product you want the
machine to return to you. If you supply the machine with different raw
materials than it expects, or if you try to return a product that\'s
different than what you told the machine to produce, the C compiler will
throw an error.

Note that a function isn\'t required to take any inputs. It doesn\'t
have to return anything back to us, either. If we modify the example
above to ask the user for their grade inside the `check` function, there
would be no need to pass the grade value into the function. And notice
that the `check` doesn\'t pass a value back. The function just prints
out a message to the screen.

You should be familiar with some basic terminology related to functions:

-   A function, call it *f*, that uses another function *g*, is said to
    *call* *g*. For example, *f* calls *g* to print the squares of ten
    numbers. *f* is referred to as the *caller* function and *g* is the
    *callee*.
-   The inputs we send to a function are called its *arguments*. When we
    declare our function, we describe the *parameters* that determine
    what type of *arguments* are acceptable to pass into the function.
    We describe these parameters to the compiler inside a set of
    parentheses next to the function\'s name.
-   A function *g* that gives some kind of answer back to *f* is said to
    *return* that answer or value. For example, *g* returns the sum of
    its arguments.

## Writing functions in C

It\'s always good to learn by example. Let\'s write a function that will
return the square of a number.

``` c
int square(int x)
{
   int square_of_x;
   square_of_x = x * x;
   return square_of_x;
}
```

To understand how to write such a function like this, it may help to
look at what this function does as a whole. It takes in an `int`, x, and
squares it, storing it in the variable square_of_x. Now this value is
returned.

The first int at the beginning of the function declaration is the type
of data that the function returns. In this case when we square an
integer we get an integer, and we are returning this integer, and so we
write `int` as the return type.

Next is the name of the function. It is good practice to use meaningful
and descriptive names for functions you may write. It may help to name
the function after what it is written to do. In this case we name the
function \"square\", because that\'s what it does - it squares a number.

Next is the function\'s first and only argument, an `int`, which will be
referred to in the function as x. This is the function\'s *input*.

In between the braces is the actual guts of the function. It declares an
integer variable called square_of_x that will be used to hold the value
of the square of x. Note that the variable square_of_x can **only** be
used within this function, and not outside. We\'ll learn more about this
sort of thing later, and we will see that this property is very useful.

We then assign x multiplied by x, or x squared, to the variable
square_of_x, which is what this function is all about. Following this is
a `return` statement. We want to return the value of the square of x, so
we must say that this function returns the contents of the variable
square_of_x.

Our brace to close, and we have finished the declaration.

Written in a more concise manner, this code performs exactly the same
function as the above:

``` c
int square(int x)
{
   return x * x;
}
```

Note this should look familiar - you have been writing functions
already, in fact - main is a function that is always written.

### In general

In general, if we want to declare a function, we write

` `*`type`*` `*`name`*`(`*`type1`*` `*`arg1`*`, `*`type2`*` `*`arg2`*`, ...)`\
` {`\
`   /* `*`code`*` */`\
` } `

We\'ve previously said that a function can take no arguments, or can
return nothing, or both. What do we write if we want the function to
return nothing? We use C\'s `void` keyword. `void` basically means
\"nothing\" - so if we want to write a function that returns nothing,
for example, we write

``` c
void sayhello(int number_of_times)
{
  int i;
  for(i=1; i <= number_of_times; i++) {
     printf("Hello!\n");
  }
}
```

Notice that there is no `return` statement in the function above. Since
there\'s none, we write `void` as the return type. (Actually, one can
use the `return` keyword in a procedure to return to the caller before
the end of the procedure, but one cannot return a value as if it were a
function.)

What about a function that takes no arguments? If we want to do this, we
can write for example

``` c
float calculate_number(void)
{
  float to_return=1;
  int i;
  for(i=0; i < 100; i++) {
     to_return += 1;
     to_return = 1/to_return;
  }
  return to_return;
}
```

Notice this function doesn\'t take any inputs, but merely returns a
number calculated by this function.

Naturally, you can combine both void return and void in arguments
together to get a valid function, also.

### Recursion

Here\'s a simple function that does an infinite loop. It prints a line
and calls itself, which again prints a line and calls itself again, and
this continues until the stack overflows and the program crashes. A
function calling itself is called recursion, and normally you will have
a conditional that would stop the recursion after a small, finite number
of steps.

``` c
      // don't run this!
void infinite_recursion()
{
    printf("Infinite loop!\n");
    infinite_recursion();
}
```

A simple check can be done like this. Note that ++depth is used so the
increment will take place before the value is passed into the function.
Alternatively you can increment on a separate line before the recursion
call. If you say print_me(3,0); the function will print the line
Recursion 3 times.

``` c
void print_me(int j, int depth)
{
   if(depth < j) {
       printf("Recursion! depth = %d j = %d\n",depth,j); //j keeps its value
       print_me(j, ++depth);
   }
}
```

Recursion is most often used for jobs such as directory tree scans,
seeking for the end of a linked list, parsing a tree structure in a
database and factorising numbers (and finding primes) among other
things.

### Static functions

If a function is to be called only from within the file in which it is
declared, it is appropriate to declare it as a static function. When a
function is declared static, the compiler will know to compile an object
file in a way that prevents the function from being called from code in
other files. Example:

``` c
static int compare( int a, int b )
{
    return (a+4 < b)? a : b;
}
```

## Using C functions

We can now *write* functions, but how do we use them? When we write
main, we place the function outside the braces that encompass main.

When we want to use that function, say, using our `calculate_number`
function above, we can write something like

``` c
 float f;
 f = calculate_number();
```

If a function takes in arguments, we can write something like

``` c
 int square_of_10;
 square_of_10 = square(10);
```

If a function doesn\'t return anything, we can just say

``` c
 say_hello();
```

since we don\'t need a variable to catch its return value.

## Functions from the C Standard Library

While the C language doesn\'t itself contain functions, it is usually
linked with the C Standard Library. To use this library, you need to add
an #include directive at the top of the C file, which may be one of the
following from C89/C90:

+---------------+---------------+---------------+---------------+---+
| -             | -             | -             | -             |   |
|   `<assert.h |   `<limits.h |   [`<signal.h |   [`<stdlib.h |   |
| >` | h "wikilink") | h "wikilink") | h "wikilink") |   |
| -   `<ctype. | -             | -             | -             |   |
| h>` | >` | h "wikilink") | h "wikilink") |   |
| h>` | .h>`](w:Math. |   `<stddef.h | .h>` | >`](w:Stddef. | h "wikilink") |   |
| h>`](w:Float. | -             | h "wikilink") |               |   |
| h "wikilink") |   `<setjmp.h | -   [`<stdio. |               |   |
|               | >` | h "wikilink") |               |   |
+---------------+---------------+---------------+---------------+---+

The functions available are:

+----------------+----------------+----------------+----------------+
| `<assert.h>`   | `<limits.h>`   | `<signal.h>`   | `<stdlib.h>`   |
+================+================+================+================+
| -              | -   (constants | -   int        | -              |
|    assert(int) |     only)      |     raise(int  |  atof(char\*), |
|                |                |     sig). This |                |
|                |                | -   void\*     |  atoi(char\*), |
|                |                |     signal(int |                |
|                |                |     sig, void  |   atol(char\*) |
|                |                |                | -              |
|                |                | (\*func)(int)) |    strtod(char |
|                |                |                |     \* str,    |
|                |                |                |     char \*\*  |
|                |                |                |     endptr ),  |
|                |                |                |                |
|                |                |                |    strtol(char |
|                |                |                |     \*str,     |
|                |                |                |     char       |
|                |                |                |                |
|                |                |                |   \*\*endptr), |
|                |                |                |                |
|                |                |                |   strtoul(char |
|                |                |                |     \*str,     |
|                |                |                |     char       |
|                |                |                |                |
|                |                |                |    \*\*endptr) |
|                |                |                | -   rand(),    |
|                |                |                |     srand()    |
|                |                |                | -   m          |
|                |                |                | alloc(size_t), |
|                |                |                |     calloc     |
|                |                |                |     (size_t    |
|                |                |                |     elements,  |
|                |                |                |     size_t     |
|                |                |                |                |
|                |                |                |  elementSize), |
|                |                |                |     r          |
|                |                |                | ealloc(void\*, |
|                |                |                |     int)       |
|                |                |                | -   free       |
|                |                |                |     (void\*)   |
|                |                |                | -   exit(int), |
|                |                |                |     abort()    |
|                |                |                | -              |
|                |                |                |    atexit(void |
|                |                |                |                |
|                |                |                |    (\*func)()) |
|                |                |                | -   getenv     |
|                |                |                | -   system     |
|                |                |                | -   qsort(void |
|                |                |                |     \*, size_t |
|                |                |                |     number,    |
|                |                |                |     size_t     |
|                |                |                |     size, int  |
|                |                |                |     (\*sor     |
|                |                |                | tfunc)(void\*, |
|                |                |                |     void\*))   |
|                |                |                | -   abs, labs  |
|                |                |                | -   div, ldiv  |
+----------------+----------------+----------------+----------------+
| `<ctype.h>`    | `<locale.h>`   | `<stdarg.h>`   | `<string.h>`   |
+----------------+----------------+----------------+----------------+
| -   isalnum,   | -   struct     | -   va_start   | -   memcpy,    |
|     isalpha,   |     lconv\*    |     (va_list,  |     memmove    |
|     isblank    |     loc        |     ap)        | -   memchr,    |
| -   iscntrl,   | aleconv(void); | -   va_arg     |     memcmp,    |
|     isdigit,   | -   char\*     |     (ap,       |     memset     |
|     isgraph    |                |     (type))    | -   strcat,    |
| -   islower,   | setlocale(int, | -   va_end     |     strncat,   |
|     isprint,   |     const      |     (ap)       |     strchr,    |
|     ispunct    |     char\*);   | -   va_copy    |     strrchr    |
| -   isspace,   |                |     (va_list,  | -   strcmp,    |
|     isupper,   |                |     va_list)   |     strncmp,   |
|     isxdigit   |                |                |     strccoll   |
| -   tolower,   |                |                | -   strcpy,    |
|     toupper    |                |                |     strncpy    |
|                |                |                | -   strerror   |
|                |                |                | -   strlen     |
|                |                |                | -   strspn,    |
|                |                |                |     strcspn    |
|                |                |                | -   strpbrk    |
|                |                |                | -   strstr     |
|                |                |                | -   strtok     |
|                |                |                | -   strxfrm    |
+----------------+----------------+----------------+----------------+
| errno.h        | math.h         | stddef.h       | time.h         |
+----------------+----------------+----------------+----------------+
| -   (errno)    | -   sin, cos,  | -   offsetof   | -   asctime    |
|                |     tan        |     macro      |     (struct    |
|                | -   asin,      |                |     tm\*       |
|                |     acos,      |                |     tmptr)     |
|                |     atan,      |                | -   clock_t    |
|                |     atan2      |                |     clock()    |
|                | -   sinh,      |                | -   char\*     |
|                |     cosh, tanh |                |                |
|                | -   ceil       |                |    ctime(const |
|                | -   exp        |                |     time_t\*   |
|                | -   fabs       |                |     timer)     |
|                | -   floor      |                | -   double     |
|                | -   fmod       |                |     d          |
|                | -   frexp      |                | ifftime(time_t |
|                | -   ldexp      |                |     timer2,    |
|                | -   log, log10 |                |     time_t     |
|                | -   modf       |                |     timer1)    |
|                | -   pow        |                | -   struct     |
|                | -   sqrt       |                |     tm\*       |
|                |                |                |                |
|                |                |                |   gmtime(const |
|                |                |                |     time_t\*   |
|                |                |                |     timer)     |
|                |                |                | -   struct     |
|                |                |                |     tm\*       |
|                |                |                |                |
|                |                |                | gmtime_r(const |
|                |                |                |     time_t\*   |
|                |                |                |     timer,     |
|                |                |                |     struct     |
|                |                |                |     tm\*       |
|                |                |                |     result)    |
|                |                |                | -   struct     |
|                |                |                |     tm\*       |
|                |                |                |     l          |
|                |                |                | ocaltime(const |
|                |                |                |     time_t\*   |
|                |                |                |     timer)     |
|                |                |                | -   time_t     |
|                |                |                |                |
|                |                |                |  mktime(struct |
|                |                |                |     tm\* ptm)  |
|                |                |                | -   time_t     |
|                |                |                |                |
|                |                |                |  time(time_t\* |
|                |                |                |     timer)     |
|                |                |                | -   char \*    |
|                |                |                |                |
|                |                |                | strptime(const |
|                |                |                |     char\*     |
|                |                |                |     buf, const |
|                |                |                |     char\*     |
|                |                |                |     format,    |
|                |                |                |     struct     |
|                |                |                |     tm\* tptr) |
|                |                |                | -   time_t     |
|                |                |                |                |
|                |                |                |  timegm(struct |
|                |                |                |     tm         |
|                |                |                |                |
|                |                |                |  \*brokentime) |
+----------------+----------------+----------------+----------------+
| float.h        | setjmp.h       | stdio.h        |                |
+----------------+----------------+----------------+----------------+
| -              | -   int        | -   fclose     | -   fread,     |
|    (constants) |                | -   fopen,     |     fwrite     |
|                | setjmp(jmp_buf |     freopen    | -   getc, putc |
|                |     env)       | -   remove     | -   getchar,   |
|                | -   void       | -   rename     |     putchar,   |
|                |     l          | -   rewind     |     fputchar   |
|                | ongjmp(jmp_buf | -   tmpfile    | -   gets, puts |
|                |     env, int   | -   clearerr   | -   printf,    |
|                |     value)     | -   feof,      |     vprintf    |
|                |                |     ferror     | -   fprintf,   |
|                |                | -   fflush     |     vfprintf   |
|                |                | -   fgetpos,   | -   sprintf,   |
|                |                |     fsetpos    |     snprintf,  |
|                |                | -   fgetc,     |     vsprintf,  |
|                |                |     fputc      |     vsnprintf  |
|                |                | -   fgets,     | -   perror     |
|                |                |     fputs      | -   scanf,     |
|                |                | -   ftell,     |     vscanf     |
|                |                |     fseek      | -   fscanf,    |
|                |                |                |     vfscanf    |
|                |                |                | -   sscanf,    |
|                |                |                |     vsscanf    |
|                |                |                | -   setbuf,    |
|                |                |                |     setvbuf    |
|                |                |                | -   tmpnam     |
|                |                |                | -   ungetc     |
+----------------+----------------+----------------+----------------+

## Variable-length argument lists

Functions with variable-length argument lists are functions that can
take a varying number of arguments. An example in the C standard library
is the `printf` function, which can take any number of arguments
depending on how the programmer wants to use it.

C programmers rarely find the need to write new functions with
variable-length arguments. If they want to pass a bunch of things to a
function, they typically define a structure to hold all those things \--
perhaps a linked list, or an array \-- and call that function with the
data in the arguments.

However, you may occasionally find the need to write a new function that
supports a variable-length argument list. To create a function that can
accept a variable-length argument list, you must first include the
standard library header `stdarg.h`. Next, declare the function as you
would normally. Next, add as the last argument an ellipsis (\"\...\").
This indicates to the compiler that a variable list of arguments is to
follow. For example, the following function declaration is for a
function that returns the average of a list of numbers:

``` c
  float average (int n_args, ...);
```

Note that because of the way variable-length arguments work, we must
somehow, in the arguments, specify the number of elements in the
variable-length part of the arguments. In the `average` function here,
it\'s done through an argument called `n_args.` In the `printf`
function, it\'s done with the format codes that you specify in that
first string in the arguments you provide.

Now that the function has been declared as using variable-length
arguments, we must next write the code that does the actual work in the
function. To access the numbers stored in the variable-length argument
list for our `average` function, we must first declare a variable for
the list itself:

``` c
  va_list myList;
```

The `va_list` type is a type declared in the `stdarg.h` header that
basically allows you to keep track of your list. To start actually using
`myList`, however, we must first assign it a value. After all, simply
declaring it by itself wouldn\'t do anything. To do this, we must call
`va_start`, which is actually a macro defined in `stdarg.h.` In the
arguments to `va_start`, you must provide the `va_list` variable you
plan on using, as well as the name of the last variable appearing before
the ellipsis in your function declaration:

``` c
#include <stdarg.h>
float average (int n_args, ...)
{
    va_list myList;
    va_start (myList, n_args);
    va_end (myList);
}
```

Now that `myList` has been prepped for usage, we can finally start
accessing the variables stored in it. To do so, use the `va_arg` macro,
which pops off the next argument on the list. In the arguments to
`va_arg`, provide the `va_list` variable you\'re using, as well as the
primitive data type (e.g. `int`, `char`) that the variable you\'re
accessing should be:

``` c
#include <stdarg.h>
float average (int n_args, ...)
{
    va_list myList;
    va_start (myList, n_args);
    
    int myNumber = va_arg (myList, int);
    va_end (myList);
}
```

By popping `n_args` integers off of the variable-length argument list,
we can manage to find the average of the numbers:

``` c
#include <stdarg.h>
float average (int n_args, ...)
{
    va_list myList;
    va_start (myList, n_args);
    
    int numbersAdded = 0;
    int sum = 0;
     
    while (numbersAdded < n_args) {
        int number = va_arg (myList, int); // Get next number from list
        sum += number;
        numbersAdded += 1;
    }
    va_end (myList);
     
    float avg = (float)(sum) / (float)(numbersAdded); // Find the average
    return avg;
}
```

By calling `average (2, 10, 20)`, we get the average of `10` and `20`,
which is `15.`

## References

fr:Programmation C/Fonctions et
procédures
it:C/Blocchi e
funzioni/Funzioni
pl:C/Funkcje
