Pointers In C - Functions
Tags: beginners, functions, c, pointers
Published: 2020-08-06 10:07:13

Pointers are arguably the most difficult feature of C to understand. But, it is one of the features which make C an excellent language. This is the third article in the series. You can read the second one [here](https://dev.to/its_srijan/pointers-in-c-arrays-and-strings-m9h).

---
###Topics - 
0.[ Call by Value v/s Call by Reference](#call)
1.[ Pointers as Function Arguments](#arguments)
2.[ Pointers as Function Return](#return)
3.[ Pointer to Function](#pointertofunction)
4.[ Array Of Pointers to Functions](#array)
5.[ Pointer to Function as an Argument](#argument)

---

###0. Call by Value v/s Call by Reference<a name = "call"></a>

Have a look at the program below.

```c
#include <stdio.h>

int multiply(int x, int y){
  int z;
  z = x * y;
  return z;
}

main(){
int x = 3, y = 5; 
int product = multiply(x,y);
printf("Product = %d\n", product);
 /* prints "Product = 15" */
}
```

The function `multiply()` takes two `int` arguments and returns their product as `int`. In the function call `multiply(x,y)`, we passed the value of `x` and `y` ( of `main()`), which are *actual arguments*, to `multiply()`.

The values of the actual arguments are passed or copied to the *formal arguments* `x` and `y` ( of `multiply()`). The `x` and `y` of `multiply()` are different from those of `main()`. This can be verified by printing their addresses.

```c
#include <stdio.h>

int multiply(int x, int y){
  printf("Address of x in multiply() = %d\n", &x);
  printf("Address of y in multiply() = %d\n", &y);
  int z;
  z = x * y;
  return z;
}

main(){
int x = 3, y = 5;
printf("Address of x in main() = %d\n", &x);
printf("Address of y in main() = %d\n", &y);
int product = multiply(x,y);
printf("Product = %d\n", product);
}

/* Output */
Address of x in main() = 6422040
Address of y in main() = 6422036
Address of x in multiply() = 6422000
Address of y in multiply() = 6422008
Product = 15
```

Since we created stored values in a new location, it costs us memory. Wouldn't it be better if we could perform the same task without wasting space?

**Call by reference** helps us achieve this. We pass the address of or the reference of the variables to the function which does not create a copy. Using the dereferencing operator `*`, we can access the value stored at those addresses.

We can rewrite the above program using call by reference as well.

```c
#include <stdio.h>

int multiply(int *x, int *y){
  int z;
  z = (*x) * (*y);
  return z;
}

main(){
int x = 3, y = 5; 
int product = multiply(&x,&y);
printf("Product = %d\n", product);
 /* prints "Product = 15" */
}
```

###1. Pointers as Function Arguments<a name = "arguments"></a>

In this section, we will look at various programs where we give `int`, `char`, arrays and strings as arguments using pointers.<a name = "here"></a>

```c
#include <stdio.h>

void add(float *a, float *b){
 float c = *a + *b;
 printf("Addition gives %.2f\n",c);
}

void subtract(float *a, float *b){
 float c = *a - *b;
 printf("Subtraction gives %.2f\n",c);
}

void multiply(float *a, float *b){
 float c = *a * *b;
 printf("Multiplication gives %.2f\n",c);
}

void divide(float *a, float *b){
 float c = *a / *b;
 printf("Division gives %.2f\n",c);
}

main(){
    printf("Enter two numbers :\n");
    float a,b;
    scanf("%f %f",&a,&b);
    printf("What do you want to do with the numbers?\nAdd : a\nSubtract : s\nMultiply : m\nDivide : d\n");
    char operation = '0';
    scanf(" %c",&operation);
    printf("\nOperating...\n\n");
    switch (operation) {
    case 'a':
        add(&a,&b);
        break;
    case 's':
        subtract(&a,&b);
        break;
    case 'm':
        multiply(&a,&b);
        break;
    case 'd':
        divide(&a,&b);
        break;
    default:
        printf("Invalid input!!!\n");

  }

}
```

We created four functions, `add()`, `subtract()`, `multiply()` and `divide()` to perform arithmetic operations on the two numbers `a` and `b`. The address of `a` and `b` was passed to the functions. Inside the function using `*` we accessed the values and printed the result.

Similarly, we can give arrays as arguments using pointer to its first element.

```c
#include <stdio.h>

void greatestOfAll( int *p){
 int max = *p;
 for(int i=0; i < 5; i++){
    if(*(p+i) > max)
        max = *(p+i);
 }
 printf("The largest element is %d\n",max);
 }
main(){
  int myNumbers[5] = { 34, 65, -456, 0, 3455};
  greatestOfAll(myNumbers);
   /* Prints :The largest element is 3455" */
}
```

Since the name of an array itself is a pointer to the first element, we send that as an argument to the function `greatestOfAll()`. In the function, we traverse through the array using loop and pointer.

```c
#include <stdio.h>
#include <string.h>

void wish(char *p){
 printf("Have a nice day, %s",p);
}

main(){
 printf("Enter your name : \n");
 char name[20];
 gets(name);
 wish(name);
}
```

Here, we pass in the string `name` to `wish()` using a pointer and print the message.

###2. Pointers as Function Return<a name = "return"></a>

```c
#include <stdio.h>

int* multiply(int *a, int *b){
 int c = *a * *b;
 return &c;
}

main(){
int a= 3, b = 5;
int *c = multiply (&a,&b);
printf("Product = %d",*c);
}
```

The function `multiply()` takes two pointers to `int`. It returns a pointer to `int` as well which stores the address where the product is stored.

It is very easy to think that the output would be 15. But it is not!!!

When `multiply()` is called, the execution of `main()` pauses and memory is now allocated for execution of `multiply()`. After its execution is completed, the memory allocated to `multiply()` is deallocated.

Therefore, though `c` ( local to `main()`) stores the address of the product. The data there is **not guaranteed** since that memory has been deallocated.

So does that mean pointers cannot be returned by a function? No!!!

We can do two things. Either store the address in the heap or global section or declare the variable to be `static` so that their values persist. 

Static variables can simply be created by using *keyword* `static` before data type while declaring the variable.

To store addresses in heap, we can use library functions `malloc()` and `calloc()` which allocate memory dynamically. The following programs will explain both the methods.

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

/* Using malloc() */

int* multiply(int *a, int *b){
 int *c = malloc(sizeof(int));
 *c = *a * *b;
 return c;
}

main(){
int a= 3, b = 5;
int *c = multiply (&a,&b);
printf("Product = %d",*c);
}

/* Using static keyword */
#include <stdio.h>

int* multiply(int *a, int *b){
 static int c;
 c = *a * *b;
 return &c;
}

main(){
int a= 3, b = 5;
int *c = multiply (&a,&b);
printf("Product = %d",*c);
}
```

Both methods return the output as 15.

###3. Pointer to Function<a name="pointertofunction"></a>

Like pointer to different data types, we also have a pointer to function as well. A pointer to function or **function pointer** stores the address of the function. Though it doesn't point to any data. It points to the first instruction in the function.

The syntax for declaring a pointer to function is - 

```c
 /* Declaring a function */
returnType functionName(parameterType1, pparameterType2, ...);

 /* Declaring a pointer to function */
returnType (*pointerName)(parameterType1, parameterType2, ...);
pointerName = &functionName; /* or pointerName = functionName; */
```

The below example will show how you can use it.

```c
int* multiply(int *a, int *b)
{
    int *c = malloc(sizeof(int));
    *c = *a * *b;
    return c;
}

main()
{ 
    int a=3,b=5;
    int* (*p)(int*, int*) = &multiply; /* or int* (*p)(int*, int*) = multiply; */
    int *c = (*p)(&a,&b); /* or int *c = p(&a,&b); */
    printf("Product = %d",*c);
}
```

The declaration for the pointer `p` to function `multiply()` can be read as ( following [operator precedence](http://unixwiz.net/techtips/reading-cdecl.html)) - *`p` is a pointer to function with two `int`eger pointers ( or two pointers to `int`) as parameters and returning a pointer to `int`*.

Since the name of the function is also a pointer to the function, the use of `&` is not necessary. Also removing `*` from the function call doesn't affect the program.

###4. Array of Pointers to Functions<a name = "array"></a>

We have already seen how to create an array of pointers to `int`, `char` etc. Similarly, we can create an array of pointers to function.

In this array, every element will store an address of a function, where all the functions are of the same type. That is, they have the same type and no. of parameters and return types.

We will modify the program discussed [here](#here). We will store the addresses of `add()`, `subtract()`, `multiply()` and `divide()` in an array make a function call through subscipts.

```c
#include <stdio.h>

void add(float *a, float *b){
 float c = *a + *b;
 printf("Addition gives %.2f\n",c);
}

void subtract(float *a, float *b){
 float c = *a - *b;
 printf("Subtraction gives %.2f\n",c);
}

void multiply(float *a, float *b){
 float c = *a * *b;
 printf("Multiplication gives %.2f\n",c);
}

void divide(float *a, float *b){
 float c = *a / *b;
 printf("Division gives %.2f\n",c);
}

main(){
    printf("Enter two numbers :\n");
    float a,b;
    scanf("%f %f",&a,&b);
    printf("What do you want to do with the numbers?\nAdd : a\nSubtract : s\nMultiply : m\nDivide : d\n");
    char operation = '0';
    scanf(" %c",&operation);
    void (*p[])(float* , float*) = {add,subtract,multiply,divide};
    printf("\nOperating...\n\n");
    switch (operation) {
    case 'a':
        p[0](&a,&b);
        break;
    case 's':
        p[1](&a,&b);
        break;
    case 'm':
        p[2](&a,&b);
        break;
    case 'd':
        p[3](&a,&b);
        break;
    default:
        printf("Invalid input!!!\n");

  }

}
```

The declaration here can be read as - *`p` is an array of pointer to functions with two `float` pointers as parameters and returning void*.

###5. Pointer to Function as an Argument<a name = "argument"></a>

Like any other pointer, function pointers can also be passed to another function, therefore known as **callback function** or **called function**. The function to which it is passed is known as **calling function**.

A better way to understand would be to look at `qsort()`, which is an inbuilt function in C. It is used to sort an array of integers, strings, structures, etc. The declaration for `qsort()` is - 

```c
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *));
```

`qsort()` takes four arguments - 
 1. a `void` pointer to the start of an array
 2. no. of elements
 3. size of each element
 4. a function pointer that takes in two `void` pointers as arguments and returns an `int`

The function pointer points to a *comparison function* that returns an integer that is greater than, equal to or less than zero, if the first argument is respectively greater than, equal to or less than the second argument.

The following program showcases its usage.

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

int compareIntegers(const void *a, const void *b)
{
  const int *x = a;
  const int *y = b;
  return *x - *y;
}

main(){

  int myArray[] = {97,59,2,83,19,97};
  int numberOfElements = sizeof(myArray) / sizeof(int);

  printf("Before sorting - \n");
  for(int i = 0; i < numberOfElements; i++)
   printf("%d ", *(myArray + i));

  qsort(myArray, numberOfElements, sizeof(int), compareIntegers);

  printf("\n\nAfter sorting - \n");
  for(int i = 0; i < numberOfElements; i++)
   printf("%d ", *(myArray + i));
 }

/* Output */

Before sorting -
97 59 2 83 19 97

After sorting -
2 19 59 83 97 97
```

Since a function name is itself a pointer, we can write `compareIntegers` as the fourth argument.

---

In this article, we saw the various use cases of pointers with functions. How pointers can be both arguments as well as return, albeit with a bit of caution in latter. We also extended our idea about pointers being used with functions to function pointers and how they are used in C.

The edits suggested by @pentacular have been included. Thanks to him/her.