Functions and Integer Single Pointer

In this section, you are going to learn

What are the calling conventions of integer single pointer ?

Call by Value

Call by Reference

int *sp;

Consider a Integer Single Pointer

int *sp;

Let us answer few basic questions about integer single pointer

If fun(x) is the function call, then fun(typeof(x)) is the prototype / definition

Function Call

Function Definition

Observations

fun(sp[0])

void fun(int x) { }

  • Call by Value

fun(sp[1])

void fun(int x) { }

  • Call by Value

fun(sp[9])

void fun(int x) { }

  • Call by Value

fun(&sp[0])

void fun(int *p) { }

  • Call by Reference

fun(&sp[1])

void fun(int *p) { }

  • Call by Reference

fun(&sp[9])

void fun(int *p) { }

  • Call by Reference

fun(*sp)

void fun(int x) { }

  • Call by Value

fun(*(sp + 1))

void fun(int x) { }

  • Call by Value

fun(*(sp + 9))

void fun(int x) { }

  • Call by Value

fun(sp)

void fun(int *p) { }

  • Call by Reference

fun(sp + 1)

void fun(int *p) { }

  • Call by Reference

fun(sp + 9)

void fun(int *p) { }

  • Call by Reference

fun(&sp)

void fun(int **p) { }

  • Call by Reference

If Declaration has ONE dereference operator, and

  • Expression has ONE dereference operator [], and

  • Expression does not have &

  • then it is call by value

If Declaration has ONE dereference operators, and

  • Expression has ONE dereference operator *, and

  • Expression does not have &

  • then it is call by value

If Declaration has ONE dereference operator, and

  • Expression has ONE dereference operators [] or *, and

  • Expression has ONE &

  • then it is call by reference

  • Example : &sp[0]

If Declaration has ONE dereference operator, and

  • Expression has ZERO dereference operator [ ] or *, and

  • Expression has ZERO & operator

  • then it is call by reference

  • Example : sp + 1, sp + 4

If Declaration has ONE dereference operator, and

  • Expression has ZERO dereference operator [ ] or *, and

  • Expression has ONE & operator

  • then it is call by reference

  • Example : &sp

Let us look at examples of Call by Value

Example for Call By Value with [ ]

  • Step 1 : Define a integer single pointer sp

int *sp;
  • Step 2 : Allocate heap memory of Bytes

sp = malloc(5 * sizeof(int));
  • Step 3 : Copy string to heap memory pointed to by sp

sp[0] = 11;
sp[1] = 22;
sp[2] = 33;
sp[3] = 44;
sp[4] = 55;
  • Step 4 : Pass an individual integer sp[2] to a function. Call by Value

fun(sp[2]);

Individual heap elements can be accessed using [ ]

In this case sp[2] is third integer in the heap

sp[2] is fully dereferenced and there is no & symbol in fun(sp[2]). Hence this is Call By Value

  • Step 5 : Define function fun

void fun(int x)
{

}
  • Step 6 : Change value of x inside function fun

void fun(int x)
{
        x = 100;

        printf("x = %d\n", x);
}
  • Step 7 : Free heap memory after use

free(sp);
  • See the full program below

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

void fun(int x)
{
        x = 100;

        printf("x = %d\n", x);
}

int main(void)
{
        int *sp;

        sp = malloc(5 * sizeof(int));

        sp[0] = 11;
        sp[1] = 22;
        sp[2] = 33;
        sp[3] = 44;
        sp[4] = 55;

        printf("----- Before call by value -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        fun(sp[2]);

        printf("----- After call by value -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        free(sp);

        return 0;
}
  • Output is as below

----- Before call by value -----
sp[0] = 11
sp[1] = 22
sp[2] = 33
sp[3] = 44
sp[4] = 55

x = 100

----- After call by value -----
sp[0] = 11
sp[1] = 22
sp[2] = 33
sp[3] = 44
sp[4] = 55

Changing value of x inside function fun DOES NOT change sp[2]

Example for Call By Value with *

  • Step 1 : Define a integer single pointer sp

int *sp;
  • Step 2 : Allocate heap memory of Bytes

sp = malloc(5 * sizeof(int));
  • Step 3 : Copy string to heap memory pointed to by sp

sp[0] = 11;
sp[1] = 22;
sp[2] = 33;
sp[3] = 44;
sp[4] = 55;
  • Step 4 : Pass an individual integer *(a + 2) to a function. Call by Value

fun( *(sp + 2) );

Individual array elements can be accessed using *

In this case *(sp + 2) is third integer in the array

*(sp + 2) is fully dereferenced and there is no & symbol in fun( *(sp + 2) ). Hence this is Call By Value

  • Step 5 : Define function fun

void fun(int x)
{

}
  • Step 6 : Change value of x inside function fun

void fun(int x)
{
        x = 100;

        printf("x = %d\n", x);
}
  • Step 7 : Free heap memory after use

free(sp);
  • See the full program below

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

void fun(int x)
{
        x = 100;

        printf("x = %d\n", x);
}

int main(void)
{
        int *sp;

        sp = malloc(5 * sizeof(int));

        sp[0] = 11;
        sp[1] = 22;
        sp[2] = 33;
        sp[3] = 44;
        sp[4] = 55;

        printf("----- Before call by value -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        fun( *(sp + 2) );

        printf("----- After call by value -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        free(sp);

        return 0;
}
  • Output is as below

----- Before call by value -----
sp[0] = 11
sp[1] = 22
sp[2] = 33
sp[3] = 44
sp[4] = 55

x = 100

----- After call by value -----
sp[0] = 11
sp[1] = 22
sp[2] = 33
sp[3] = 44
sp[4] = 55

Changing value of x inside function fun DOES NOT change *(sp + 2)

Remember sp[2] and *(sp + 2) are one and the same

Let us look at examples of Call by Reference

Example for Call By Reference with &sp[ ]

  • Step 1 : Define a integer single pointer sp

int *sp;
  • Step 2 : Allocate heap memory of Bytes

sp = malloc(5 * sizeof(int));
  • Step 3 : Copy string to heap memory pointed to by sp

sp[0] = 11;
sp[1] = 22;
sp[2] = 33;
sp[3] = 44;
sp[4] = 55;
  • Step 4 : Pass address of an individual integer &sp[2] to a function. Call by Reference

fun( &sp[2] );

Address of individual heap elements can be accessed using &

In this case &sp[2] is the address of third integer in the heap

Since we are passing address of third integer to function fun, it is called call by reference with respect to third integer

  • Step 5 : Define function fun

void fun(int *x)
{

}
  • Step 6 : Change value of *x inside function fun

void fun(int *x)
{
        *x = 100;

        printf("*x = %d\n", *x);
}
  • Step 7 : Free heap memory after use

free(sp);
  • See the full program below

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

void fun(int *x)
{
        *x = 100;

        printf("*x = %d\n", *x);
}

int main(void)
{
        int *sp;

        sp = malloc(5 * sizeof(int));

        sp[0] = 11;
        sp[1] = 22;
        sp[2] = 33;
        sp[3] = 44;
        sp[4] = 55;

        printf("----- Before call by reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        fun( &sp[2] );

        printf("----- After call by reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        free(sp);

        return 0;
}
  • Output is as below

----- Before call by reference -----
sp[0] = 11
sp[1] = 22
sp[2] = 33
sp[3] = 44
sp[4] = 55
*x = 100

----- After call by reference -----
sp[0] = 11
sp[1] = 22
sp[2] = 100
sp[3] = 44
sp[4] = 55

Changing value of *x inside function fun CHANGES sp[2] in sp

Example for Call By Reference with (sp + x)

  • Step 1 : Define a integer single pointer sp

int *sp;
  • Step 2 : Allocate heap memory of Bytes

sp = malloc(5 * sizeof(int));
  • Step 3 : Copy string to heap memory pointed to by sp

sp[0] = 11;
sp[1] = 22;
sp[2] = 33;
sp[3] = 44;
sp[4] = 55;
  • Step 4 : Pass address of individual integer sp + 2 to a function. Call by Reference

fun( sp + 2 );

In this case sp + 2 is the address of third integer in the heap

Since we are passing address of third integer to function fun, it is called call by reference with respect to third integer

  • Step 5 : Define function fun

void fun(int *x)
{

}
  • Step 6 : Change value of *x inside function fun

void fun(int *x)
{
        *x = 100;

        printf("*x = %d\n", *x);
}
  • Step 7 : Free heap memory after use

free(sp);
  • See the full program below

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

void fun(int *x)
{
        *x = 100;

        printf("*x = %d\n", *x);
}

int main(void)
{
        int *sp;

        sp = malloc(5 * sizeof(int));

        sp[0] = 11;
        sp[1] = 22;
        sp[2] = 33;
        sp[3] = 44;
        sp[4] = 55;

        printf("----- Before call by reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        fun( sp + 2 );

        printf("----- After call by reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        free(sp);

        return 0;
}
  • Output is as below

----- Before call by reference -----
sp[0] = 11
sp[1] = 22
sp[2] = 33
sp[3] = 44
sp[4] = 55

*x = 100

----- After call by reference -----
sp[0] = 11
sp[1] = 22
sp[2] = 100
sp[3] = 44
sp[4] = 55

Changing value of *x inside function fun CHANGES sp[2]

  • Step 1 : Define a integer single pointer sp

int *sp;
  • Step 2 : Allocate heap memory of Bytes

sp = malloc(5 * sizeof(int));
  • Step 3 : Copy string to heap memory pointed to by sp

sp[0] = 11;
sp[1] = 22;
sp[2] = 33;
sp[3] = 44;
sp[4] = 55;
  • Step 4 : Pass full array array to a function

fun( sp );

Note that we are passing starting address of array

Hence function fun has read and write access to all Bytes of array

  • Step 5 : Define a function

void fun(int *x)
{
        x[0] = 111;
        x[1] = 222;
        x[2] = 333;
        x[3] = 444;
        x[4] = 555;
}

function fun has access to all integers

  • Step 6 : Free heap memory after use

free(sp);
  • See full program below

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

void fun(int *x)
{
        x[0] = 111;
        x[1] = 222;
        x[2] = 333;
        x[3] = 444;
        x[4] = 555;
}

int main(void)
{
        int *sp;

        sp = malloc(5 * sizeof(int));

        sp[0] = 11;
        sp[1] = 22;
        sp[2] = 33;
        sp[3] = 44;
        sp[4] = 55;

        printf("----- Before call by reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        fun(sp);

        printf("----- After call by reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        free(sp);

        return 0;
}
  • Output is as below

----- Before call by reference -----
sp[0] = 11
sp[1] = 22
sp[2] = 33
sp[3] = 44
sp[4] = 55

----- After call by reference -----
sp[0] = 111
sp[1] = 222
sp[2] = 333
sp[3] = 444
sp[4] = 555
  • Step 1 : Define a integer single pointer sp

int *sp;
  • Step 2 : Allocate heap memory of Bytes

sp = malloc(5 * sizeof(int));
  • Step 3 : Copy string to heap memory pointed to by sp

sp[0] = 11;
sp[1] = 22;
sp[2] = 33;
sp[3] = 44;
sp[4] = 55;
  • Step 4 : Pass full array by reference with relative addressing

fun( sp + 2 );

Note that we are passing part of the array by reference

In this case, we are passing address of 3rd integer

Hence function fun has read and write access to Integers at indexes 2,3,4 in forward direction

Hence function fun has read and write access to Integers 0, 1 in backward direction

  • Step 5 : Define a function

void fun(int *x)
{
        x[-2] = 111; // Same as sp[0]
        x[-1] = 222; // Same as sp[1]
        x[0]  = 333; // Same as sp[2]
        x[1]  = 444; // Same as sp[3]
        x[2]  = 555; // Same as sp[4]
}

Note the relative access mechanism used inside function fun

  • See full program below

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

void fun(int *x)
{
        x[-2] = 111; // Same as sp[0]
        x[-1] = 222; // Same as sp[1]
        x[0]  = 333; // Same as sp[2]
        x[1]  = 444; // Same as sp[3]
        x[2]  = 555; // Same as sp[4]
}

int main(void)
{
        int *sp;

        sp = malloc(5 * sizeof(int));

        sp[0] = 11;
        sp[1] = 22;
        sp[2] = 33;
        sp[3] = 44;
        sp[4] = 55;

        printf("----- Before call by reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        fun(sp + 2);

        printf("----- After call by reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        free(sp);

        return 0;
}
  • Output is as below

----- Before call by reference -----
sp[0] = 11
sp[1] = 22
sp[2] = 33
sp[3] = 44
sp[4] = 55

----- After call by reference -----
sp[0] = 111
sp[1] = 222
sp[2] = 333
sp[3] = 444
sp[4] = 555
  • Step 1 : Define a integer single pointer sp

int *sp;
  • Step 2 : Allocate heap memory of Bytes

sp = malloc(5 * sizeof(int));
  • Step 3 : Copy string to heap memory pointed to by sp

sp[0] = 11;
sp[1] = 22;
sp[2] = 33;
sp[3] = 44;
sp[4] = 55;
  • Step 4 : Pass the address of array sp to function fun

fun(&sp);
  • Step 5 : Define the function fun

void fun( int **dp)
{

}

Note that int **dp is a pointer to a integer single pointer

  • Step 6 : Access individual integers inside function fun

void fun( int **dp )
{
        //Change individual integers
        (*dp)[0] = 111;
        (*dp)[1] = 222;
        (*dp)[2] = 333;
        (*dp)[3] = 444;
        (*dp)[4] = 555;
}
  • Step 8 : Free heap memory after use

free(sp);
  • See the full program below

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

void fun( int **dp )
{
        //Change individual integers
        (*dp)[0] = 111;
        (*dp)[1] = 222;
        (*dp)[2] = 333;
        (*dp)[3] = 444;
        (*dp)[4] = 555;
}

int main(void)
{
        int *sp;

        sp = malloc(5 * sizeof(int));

        sp[0] = 11;
        sp[1] = 22;
        sp[2] = 33;
        sp[3] = 44;
        sp[4] = 55;

        printf("----- Before call by reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        fun(&sp);

        printf("----- After call by reference -----\n");

        for (int i = 0; i < 5; i++)
        {
                printf("sp[%d] = %d\n", i, sp[i]);
        }

        free(sp);

        return 0;
}
  • Output is as below

----- Before call by reference -----
sp[0] = 11
sp[1] = 22
sp[2] = 33
sp[3] = 44
sp[4] = 55

----- After call by reference -----
sp[0] = 111
sp[1] = 222
sp[2] = 333
sp[3] = 444
sp[4] = 555