C Pointer to Pointer, Pointer to Functions, Array of Pointers Explained with Examples

by Himanshu Arora on January 27, 2012

In C programming language, the concept of pointers is the most powerful concept that makes C stand apart from other programming languages. In the part-I of this series we discussed the fundamental concepts around C pointers.

In this article, we will try to develop 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. Array of pointers with an example
  4. Pointer to functions with an example

1. C Constant Pointer and Pointer to Constant

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

C Constant pointer

A pointer is said to be constant pointer when the address its pointing to cannot be changed.

Lets 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 case of a constant pointer, once a pointer holds an address, it cannot change it. This means a constant pointer, if already pointing to an address, cannot point to a new address.

If we see the example above, then if ‘ptr’ would have been 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, 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 we see that, as expected, compiler throws an error since we tried to change the address held by constant pointer.

Now, we should be clear with this concept. Lets 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.

Lets 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 character ‘ch’. In the last line, we change the value at address pointer by ‘ptr’. But if this 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 its 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 was compiled, compiler gave 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 ie we cannot change the value pointed to by a constant pointer.

2. 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 pointing to pointers.

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

Lets 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, pointer p1 holds the address of pointer p2. Pointer p2 holds the address of character ‘ch’.

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

Now, in code ‘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 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’

I think that should pretty much clear the concept, lets 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]

3. C Array of Pointers

Just like array of integers or characters, there can be 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.

Lets take a working example :

#include<stdio.h> 

int main(void)
{
    char *p1 = "Himanshu";
    char *p2 = "Arora";
    char *p3 = "India"; 

    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 index of array. Let’s see the output :

$ ./arrayofptr 

 p1 = [Himanshu] 

 p2 = [Arora] 

 p3 = [India] 

 arr[0] = [Himanshu] 

 arr[1] = [Arora] 

 arr[2] = [India]

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

4. C Function Pointers

Just like pointer 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.

Lets 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, name of the function can be treated as starting address of the function so we can assign the address of function to function pointer using function’s name. Lets see the output :

$ ./fptr 

 a = 2 

 b = 3 

 a = 2 

 b = 3

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

To conclude, in this article we touched some of the advanced concepts related to pointers. There can be some interesting problems related to pointers, which we might cover in some future article.


Share

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

{ 6 comments… read them below or add one }

1 cee January 27, 2012 at 3:43 am

Hi,
This article is so good, I will print it out for my apprentice (and myself).
It would be nice if this blog had a ‘print this site with all pictures and the whole formatting’ option.

Best Regards,
cee

2 Himanshu January 27, 2012 at 4:18 am

@cee
Thanks!!!

3 Makis January 27, 2012 at 6:40 am

Very nice examples. Good work! I believe it would also be nice to cover some dynamic memory fundamentals using pointers (ie dynamic single and two-dimensional arrays). Also consider the possibility of covering this dynamic memory tutorial not only for C but also for the C++ language.

4 apol January 27, 2012 at 12:12 pm

Yeah ! you’ve wrote it as you said before the end of january ;-) Thanks a lot for this article and your site in general.

5 Jay January 29, 2012 at 4:20 am

The article is very nice..and useful as well.
If the uses mentioned then it would be more and more helpful.

6 Balakrishnan M February 6, 2012 at 12:44 am

Clearly explained.. Useful one !!

Leave a Comment

Previous post:

Next post: