helper ask help
helper ask help

Reputation: 71

How do you create an array of pointers in C?

How do I create an array of pointers where each element holds a pointer to some other value

For example if I have

int** arr[5] = {0xbfjeabfbfe,0x...}; //is it the right way to do it?

And what it means to have an array type of void? like void **newArray[5];

And let's say I want to dynamically allocate memory for an array of pointers using malloc or calloc!! What will be the syntax be?

Upvotes: 5

Views: 30542

Answers (3)

David C. Rankin
David C. Rankin

Reputation: 84541

How do you create an array of pointers in C?

To create an array of pointers in C, you have one option, you declare:

  type *array[CONST];  /* create CONST number of pointers to type */

With C99+ you can create a Variable Length Array (VLA) of pointers, e.g.

  type *array[var];   /* create var number of pointers to type */

The standard defines both in C11 Standard - 6.7.6.2 Array declarators and discusses subscripting in C11 Standard - 6.5.2.1 Array subscripting.

A short example using an array of pointers, assigning a pointer to each row in a 2D array to an array of pointers to int, e.g.

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

#define COL 3
#define MAX 5

int main (void) {

    int arr2d[MAX][COL] = {{ 0 }},  /* simple 2D array */
        *arr[MAX] = { NULL },       /* 5 pointers to int */
        i, j, v = 0;

    for (i = 0; i < MAX; i++) {     /* fill 2D array */
        for (j = 0; j < COL; j++)
            arr2d[i][j] = v++;
        arr[i] = arr2d[i];          /* assing row-pointer to arr */
    }

    for (i = 0; i < MAX; i++) {     /* for each pointer */
        for (j = 0; j < COL; j++)   /* output COL ints */
            printf (" %4d", arr[i][j]);
        putchar ('\n');
    }
}

Example Use/Output

$ ./bin/array_ptr2int_vla
    0    1    2
    3    4    5
    6    7    8
    9   10   11
   12   13   14

Another fundamental of C is the pointer-to-pointer, but it is not an "Array", though it is routinely called a "dynamic array" and can be allocated and indexed simulating an array. The distinction between an "Array" and a collection of pointers is that with an Array, all values are guaranteed to be sequential in memory -- there is no such guarantee with a collection of pointers and the memory locations they reference.

So What Does int **arr[CONST] Declare?

In your question you posit a declaration of int** arr[5] = {0xbfjeabfbfe,0x...};, so what does that declare? You are declaring Five of something, but what? You are declaring five pointer-to-pointer-to-int. Can you do that? Sure.

So what do you do with a pointer-to-pointer-to-something? The pointer-to-poitner forms the backbone of dynamically allocated and reallocated collection of types. They are commonly termed "dynamically allocated arrays", but that is somewhat a misnomer, because there is no guarantee that all values will be sequential in memory. You will declare a given number of pointers to each int** in the array. You do not have to allocate an equal number of pointers.

(note: there is no guarantee that the memory pointed to by the pointers will even be sequential, though the pointers themselves will be -- make sure you understand this distinction and what an "Array" guarantees and what pointers don't)

int** arr[5] declares five int**. You are then free to assign any address to you like to each of the five pointers, as long as the type is int**. For example, you will allocate for your pointers with something similar to:

  arr[i] = calloc (ROW, sizeof *arr[i]);  /* allocates ROW number of pointers */

Then you are free to allocate any number of int and assign that address to each pointer, e.g.

  arr[i][j] = calloc (COL, sizeof *arr[i][j]); /* allocates COL ints */

You can then loop over the integers assigning values:

  arr[i][j][k] = v++;

A short example using your int** arr[5] type allocation could be similar to:

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

#define ROW 3
#define COL ROW
#define MAX 5

int main (void) {

    int **arr[MAX] = { NULL },  /* 5 pointer-to-pointer-to-int */
        i, j, k, v = 0;

    for (i = 0; i < MAX; i++) { /* allocate ROW pointers to each */
        if ((arr[i] = calloc (ROW, sizeof *arr[i])) == NULL) {
            perror ("calloc - pointers");
            return 1;
        }
        for (j = 0; j < ROW; j++) { /* allocate COL ints each pointer */
            if ((arr[i][j] = calloc (COL, sizeof *arr[i][j])) == NULL) {
                perror ("calloc - integers");
                return 1;
            }
            for (k = 0; k < COL; k++)   /* assign values to ints */
                arr[i][j][k] = v++;
        }
    }

    for (i = 0; i < MAX; i++) { /* output each pointer-to-pointer to int */
        printf ("pointer-to-pointer-to-int: %d\n\n", i);
        for (j = 0; j < ROW; j++) {     /* for each allocated pointer */
            for (k = 0; k < COL; k++)   /* output COL ints */
                printf ("  %4d", arr[i][j][k]);
            free (arr[i][j]);   /* free the ints */
            putchar ('\n');
        }
        free (arr[i]);      /* free the pointer */
        putchar ('\n');
    }

    return 0;
}

You have allocated for five simulated 2D arrays assigning the pointer to each to your array of int **arr[5], the output would be:

Example Use/Output

$ ./bin/array_ptr2ptr2int
pointer-to-pointer-to-int: 0

     0     1     2
     3     4     5
     6     7     8

pointer-to-pointer-to-int: 1

     9    10    11
    12    13    14
    15    16    17

pointer-to-pointer-to-int: 2

    18    19    20
    21    22    23
    24    25    26

pointer-to-pointer-to-int: 3

    27    28    29
    30    31    32
    33    34    35

pointer-to-pointer-to-int: 4

    36    37    38
    39    40    41
    42    43    44

Hopefully this has helped with the distinction between an array of pointers, and an array of pointers-to-pointer and shown how to declare and use each. If you have any further questions, don't hesitate to ask.

Upvotes: 8

user9614249
user9614249

Reputation:

How do I create an array of pointers where each element holds a pointer to some other value

An array of arrays can be though of as a 3D matrix

int*** arr;    // Points to an array of arrays (3 Dimensions)
int** arr[0];  // Points to an array           (2 Dimensions)
int* arr[0][0];// Points to a single element   (1 Dimension)

If you know the size before hand you can initialize a 3D array like this:

int arr[2][2][2] = {
   { {1, 2}, {3, 4} },
   { {5, 6}, {7, 8} },
}

But its not very readable for non trivial n-dimensional arrays. Another approach is to loop over each dimension.

int*** arr;
int dimensions = 10;

arr = malloc(dimensions * sizeof(int**)); // Allocate an array of 2D arrays

for (int i = 0; i < dimensions; i++) {
  arr[i] = malloc(dimensions * sizeof(int*)); // Allocate an array of arrays 

  for (int j = 0; j < dimensions; j++) {
      arr[i][j] = malloc(dimensions * sizeof(int)); // Allocate array

      for (int k = 0; k < dimensions; k++) {
          arr[i][j][k] = 0; // Fill each element with 0's
      }
  }
}

This approach also lets to dynamically allocate the arrays.

And what it means to have an array type of void? like void **newArray[5];

void* is a pointer to an unknown type. If int* means a pointer to an int, void* means a pointer to a value who's type is unknown.

Upvotes: 2

pm100
pm100

Reputation: 50120

An array of pointers to ints;

int x = 1;
int y = 42;
int z = 12;

int * array[3];

array[0] = &x;
array[1] = &y;
array[2] = &z;

alternate syntax

int * array[] = {&x,&y,&z};

keeping it simple. Work upwards from there

Upvotes: 3

Related Questions