Pointers in C – Part 2

This article is the continuation of the Series on the C programming tutorial and carries the discussion on C language programming and its implementation. It aims to provide easy and practical examples for understanding the C program. In our last article, we have seen the Basic concepts of pointers in C programming. This is the continuation of the last tutorial. Now, we will discuss Pointer’s Advanced concepts. 

You can also read different types of pointers, Qualifiers in C, and Embedded Interview topics.

Pointers Advanced concepts

Now, we will try to develop an understanding of some of the relatively complex concepts. The following are explained in this article with examples:

  1. Constant pointer and pointer to constant.
  2. Pointer to pointer with an example
  3. An array of pointers with an example
  4. Pointer to functions with an example

C Constant Pointer and Pointer to Constant

As a developer, you should understand the difference between a constant pointer and a pointer to a constant.

C Constant pointer

A pointer is said to be a constant pointer when the address that is pointing to, cannot be changed.

Let’s take an example :

char ch, c;
char *ptr = &ch;
ptr = &c;

In the above example, we defined two characters (‘ch’ and ‘c’) and a character pointer ‘ptr’. First, the pointer ‘ptr’ contained the address of ‘ch’ and in the next line, it contained the address of ‘c’. In other words, we can say that Initially ‘ptr’ pointed to ‘ch’ and then it pointed to ‘c’.

But in the case of a constant pointer, once a pointer holds an address, that address cannot be changed. That means a constant pointer cannot point to a new address if it is already pointing to an address.

If we see the example above,  if we declare ‘ptr’ as a constant pointer, then the third line would have not been valid.

A constant pointer is declared as :

<type-of-pointer> *const <name-of-pointer>

For example :

#include<stdio.h>

int main(void)
{
    char ch = 'c';
    char c = 'a';

    char *const ptr = &ch; // A constant pointer
    ptr = &c;              // Trying to assign new address to a constant pointer. WRONG!!!!

    return 0;
}

When the code above is compiled, the compiler gives the following error :

$ gcc -Wall constptr.c -o constptr
constptr.c: In function ‘main’:
constptr.c:9: error: assignment of read-only variable ‘ptr’

So as expected, the compiler throws an error when we try to change the address held by the constant pointer.

Now, we should be clear with this concept. Let’s move on.

C Pointer to Constant

This concept is easy to understand as the name simplifies the concept. Yes, as the name itself suggests, this type of pointer cannot change the value at the address pointed by it.

Let’s understand this through an example :

char ch = 'c';
char *ptr = &ch;
*ptr = 'a';

In the above example, we used a character pointer ‘ptr’ that points to the character ‘ch’. In the last line, we change the value at the address pointer by ‘ptr’. But if ‘ptr‘ would have been a pointer to a constant, then the last line would have been invalid because a pointer to a constant cannot change the value at the address it is pointing to.

A pointer to a constant is declared as :

const <type-of-pointer> *<name-of-pointer>;

For example :

#include<stdio.h>

int main(void)
{
    char ch = 'c';
    const char *ptr = &ch; // A constant pointer 'ptr' pointing to 'ch'
    *ptr = 'a';// WRONG!!! Cannot change the value at address pointed by 'ptr'.

    return 0;
}

When the above code is compiled, the compiler will give the following error :

$ gcc -Wall ptr2const.c -o ptr2const
ptr2const.c: In function ‘main’:
ptr2const.c:7: error: assignment of read-only location ‘*ptr’

So, now we know the reason behind the error above (i.e.) we cannot change the value pointed to by a constant pointer.

C Pointer to Pointer

Till now, we have used or learned pointer to a data type like character, integer, etc. But in this section, we will learn about pointers that are pointing to the other pointers.

As the definition of a pointer says, it is a special variable that can store the address of another variable. Then the other variable can very well be a pointer. This means that it is perfectly legal for a pointer to be pointing to another pointer.

Suppose we have a pointer ‘p1’ that points to yet another pointer ‘p2’ that points to a character ‘ch’. In memory, the three variables can be visualized as :

So, we can see that in memory. The pointer p1 holds the address of the pointer p2. The pointer p2 holds the address of the character ‘ch’.

So ‘p2’ is a pointer to the character ‘ch’, while ‘p1’ is a pointer to ‘p2’ or we can also say that ‘p2’ is a pointer to pointer to the character ‘ch’.

Now,  ‘p2’ can be declared as :

char *p2 = &ch;

But ‘p1’ is declared as :

char **p1 = &p2;

So we see that ‘p1’ is a double pointer (ie pointer to a pointer to a character) and hence the two *s in the declaration.

Now,

  • p1’ is the address of ‘p2’ ie 5000
  • *p1’ is the value held by ‘p2’ ie 8000
  • **p1’ is the value at 8000 ie ‘c

Let us take a small example :

#include<stdio.h>

int main(void)
{
    char **ptr = NULL;
    char *p = NULL;
    char c = 'd';

    p = &c;
    ptr = &p;

    printf("\n c = [%c]\n",c);
    printf("\n *p = [%c]\n",*p);
    printf("\n **ptr = [%c]\n",**ptr);

    return 0;
}

Here is the output :

$ ./doubleptr
c = [d]
*p = [d]
**ptr = [d]

C Array of Pointers

Just like an array of integers or characters, there can be an array of pointers too.

An array of pointers can be declared as :

<type> *<name>[<number-of-elements];

For example :

char *ptr[3];

The above line declares an array of three character pointers.

Let us take a working example :

#include<stdio.h>

int main(void)
{
    char *p1 = "Embetronicx";
    char *p2 = "Embedded";
    char *p3 = "Tutorials";

    char *arr[3];

    arr[0] = p1;
    arr[1] = p2;
    arr[2] = p3;

    printf("\n p1 = [%s] \n",p1);
    printf("\n p2 = [%s] \n",p2);
    printf("\n p3 = [%s] \n",p3);

    printf("\n arr[0] = [%s] \n",arr[0]);
    printf("\n arr[1] = [%s] \n",arr[1]);
    printf("\n arr[2] = [%s] \n",arr[2]);

    return 0;
}

In the above code, we took three-pointers pointing to three strings. Then we declared an array that can contain three-pointers. We assigned the pointers ‘p1’, ‘p2’, and ‘p3’ to the 0,1 and 2 indexes of the array. Let’s see the output :

$ ./arrayofptr
p1 = [Embetronicx]
p2 = [Embedded]
p3 = [Tutorials]
arr[0] = [Embetronicx]
arr[1] = [Embedded]
arr[2] = [Tutorials]

So, we see that the array holds the address of strings.

C Function Pointers

Just like pointers to characters, integers, etc., we can have pointers to functions.

A function pointer can be declared as:

<return type of function> (*<name of pointer>) (type of function arguments)

For example:

int (*fptr)(int, int)

The above line declares a function pointer ‘fptr’ that can point to a function whose return type is ‘int’ and takes two integers as arguments.

Let’s take a working example :

#include<stdio.h>

int func (int a, int b)
{
    printf("\n a = %d\n",a);
    printf("\n b = %d\n",b);

    return 0;
}

int main(void)
{
    int(*fptr)(int,int); // Function pointer

    fptr = func;         // Assign address to function pointer

    func(2,3);
    fptr(2,3);

    return 0;
}

In the above example, we defined a function ‘func’ that takes two integers as inputs and returns an integer. In the main() function, we declare a function pointer ‘fptr’ and then assign value to it. Note that, the name of the function can be treated as starting address of the function so we can assign the address of a function to the function pointer using the function’s name. Let’s see the output :

$ ./fptr 
a = 2 
b = 3
a = 2
b = 3

From the above output, we see that calling the function through the function pointer produces the same output as calling the function from its name.

If both methods are executing in the same way, then what is the use of this function pointer? Now we can see the uses of the function pointer.

Uses of Function pointer

  • Function pointers can be useful when you want to create a callback mechanism and need to pass the address of a function to another function.
  • They can also be useful when you want to store an array of functions, to call dynamically for example.

I think this might help you. If you have any doubts, please comment below. In our next tutorial, we will discuss the different types of pointers in C programming.

You can also read the below tutorials.

Linux Device Driver TutorialsC Programming Tutorials
FreeRTOS TutorialsNuttX RTOS Tutorials
RTX RTOS TutorialsInterrupts Basics
I2C Protocol – Part 1 (Basics)I2C Protocol – Part 2 (Advanced Topics)
STM32 TutorialsLPC2148 (ARM7) Tutorials
PIC16F877A Tutorials8051 Tutorials
Unit Testing in C TutorialsESP32-IDF Tutorials
Raspberry Pi TutorialsEmbedded Interview Topics
Reset Sequence in ARM Cortex-M4BLE Basics
VIC and NVIC in ARMSPI – Serial Peripheral Interface Protocol
STM32F7 Bootloader TutorialsRaspberry PI Pico Tutorials
STM32F103 Bootloader TutorialsRT-Thread RTOS Tutorials
Zephyr RTOS Tutorials - STM32Zephyr RTOS Tutorials - ESP32
AUTOSAR TutorialsUDS Protocol Tutorials
Product ReviewsSTM32 MikroC Bootloader Tutorial
VHDL Tutorials
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Table of Contents