An array of pointers and A pointer to an array in C6 min read

A pointer in C simply is just a variable holding address in the primary memory of another variable, a pointer shouldn’t be dreaded like people usually think. However, there are some situations of using pointers in which we need carefully ruminate to see how they can be used. In this article, we are going to point out the differences between an array of pointers and a pointer to an array in C.

Array of pointers

An array of pointers is an array in which each element in this array is essentially a pointer. It’s also known as pointer array. Here is the syntax for declaring an array of pointers:

datatype *identifier[ARRAY_SIZE];

For example, now you want to declare an array 3 integer pointers, we can simply do this:

int *arr[3];

To work with this, we can assign some addresses of integer values and later then we can get those values through dereferencing:

#include <stdio.h>

int main() {
    int arr[] = {1, 2, 3, 4, 5}; 
    int *ptr[5], i;
    for(i = 0; i < 5; i++) {
        ptr[i] = &arr[i]; 
    }
    for(i = 0; i < 5; i++) {
        printf("Value of arr[%d] is: %d, at address: %x\n", i, *(ptr[i]), ptr[i]); // loop through each of element in the pointer array, get the value stored at this element and 
    }
    return 0;
}

Let’s break down what’s happening here:

  • First we declare and define an integer array with 5 elements, int arr[] = {1, 2, 3, 4, 5};
  • We create an array of pointers named ptr which will hold the address of each element of the arr.
  • Then we assign the address of each element in arr to the ptr array using & operator.
  • Finally, because each of the elements in ptr stores the address of an integer, then we can dereference these addresses to get the actual value, we also output the value of every element in ptr array.

Output:

Value of arr[0] is: 1, at address: e01638d0
Value of arr[1] is: 2, at address: e01638d4
Value of arr[2] is: 3, at address: e01638d8
Value of arr[3] is: 4, at address: e01638dc
Value of arr[4] is: 5, at address: e01638e0

An array of pointers can acts as a multidimensional array as well, because each element is a pointer, as we already know, a pointer can point to an array.

For example, a string is basically an array of characters terminated will a null terminal, '\0', hence to create an array of strings, meaning like a sentence, we can formulate this by two different ways, either:

char sentence[NO_OF_WORDS][NO_OF_CHARACTERS_PER_WORD];

Or we can use an array of poiters:

char *sentence[NO_OF_WORDS];

When we declare an array like this, we basically say that this is an array with NO_OF_WORDS size, and each element is a pointer to a character.

#include <stdio.h>
int main() {
    char *names[4] = {"Nam", "Ethan", "Rick", "Morty"};
    int i;
    for(i = 0; i < 4; i++) {
        printf("The string at names[%d] is: %s\n", i, names[i]);
    }
}

Let’s break down what’s happening here:

  • In the first line, we create an array of pointers, char *names[4], note that up to this point, we’ve just allocated memory to pointers to strings, but we also must provide the memory for strings themselves, hence we create a few static strings for this purpose.
  • Then we loop through each element of the array and get dereference the value, because the %s format specifier accepts an address, hence we just need the address we store on each array element and get the string value.

Output:

The string at names[0] is: Nam
The string at names[1] is: Ethan
The string at names[2] is: Rick
The string at names[3] is: Morty

A pointer to an array

Usually, we declare an array, and a pointer points to this array will have the address of the first array element:

int nums[] = {2, 3, 4, 5};
int *ptr = nums;
printf("%d", ptr == &nums[0]); // 1 means true

This pointer can only point to one element at a time, i.e the first array element in this case. On the other hand, a pointer to an array is a pointer in which it can retain the address of a whole array instead of just a single element, it’s also known as an array pointer. Here is the syntax:

datatype (*identifier)[SIZE_OF_THE_ARRAY];

Let’s demonstrate the difference between a pointer points to a single element and a pointer that points to a whole array:

#include <stdio.h>
int main() {

    int nums[] = {1, 2, 3, 4, 5};
    int *ptr = nums; // pointer points to an integer

    int (*arrPtr)[5] = nums; // pointer points to array of integers
    printf("Address of ptr before being increased=%x\n", ptr);

    ptr++;
    printf("Address of ptr after being increased= %x\n\n", ptr);

    printf("Address of arrPtr before being increased=%x\n", arrPtr);

    arrPtr++;
    printf("Address of arrPtr after being increased= %x", arrPtr);
}

If we run this code, here is the output that you might get:

Address of ptr before being increased=eec698d0
Address of ptr after being increased= eec698d4

Address of arrPtr before being increased=eec698d0
Address of arrPtr after being increased= eec698e4

The ptr points to the address of the first integer element, as a result, when performing arithmetic operations such as ++ or --, the address will be added by 4 or substructed by 4 as an offset to get the address of the next or previous elements.

However, it’s not the case with arrPtr, because it’s pointer the whole array, thus, when we increase the address of this pointer, it is shifted toward 20 bytes (as the total bytes of an integer array with 5 elements).

So how can we deference the values that stored in the array pointer? It is not possible for us to just increase the pointer each time as we usually do for a pointer to single value. This is how we can accomplish this:

#include <stdio.h>
int main() {

    int nums[] = {1, 2, 3, 4, 5};
    int (*arrPtr)[5] = nums;

    int i;
    for(i = 0; i < 5; i++) {
        printf("The address: %x\tThe value:%d\n", (*arrPtr + i), *(*arrPtr + i));
    }
}

Output:

The address: eeaa28d0	The value:1
The address: eeaa28d4	The value:2
The address: eeaa28d8	The value:3
The address: eeaa28dc	The value:4
The address: eeaa28e0	The value:5

The arrPtr is a pointer to an array of 5 integer elements. The only line that needs to pay attention here is the printf line lied inside the for loop.

Let’s interpret this piece of code (*arrPtr + i):

  • The * means dereference value that store at this address, because arrPtr is a pointer to an array, hence the value stored on this address is actually an address of an element in the nums array, in the first pass, (*attrPtr + 0) will give the address of the first element of the nums array.
  • So on and so forth for the next passes.

Let’s interpret *(*arrPtr + i):

  • We already perceived that (*arrPtr + i) give you the address of the i-th element in the nums array.
  • So we put another asterisk outside, which means dereferencing the value at this (*arrPtr + i) address, hence it gives us the actual values stored in the nums array.
  • This works the same as *(ptr + i) in case ptr is a pointer to a single element of the array.

Conclusion

To wrap up, to distinguish an array of pointers from a pointer to an array in the first glance, just remember their syntax.

For an array of pointers:

datatype *identifier[SIZE];
e.g
int *arr[5];

For a pointer to an array:

datatype (*identifier)[SIZE];
e.g
int (*arr[5]);

Next Article

Subscribe to my newsletter to get weekly updates

Categories

Archives