0

How to create a pointer to the following 2D array pointer int **arr. I am looking for something similar to int*** arr and its allocation, deallocation, accessing and usage.

int main()
{
  int** arr;

  int row = 11;
  int col = 2;
  int i,j;

  arr = (int**)malloc(sizeof(int*)*row);
  for (i=0; i<row; ++i){
    arr[i] = (int*)malloc(sizeof(int)*col);
  }

  for (i = 0; i < row; i++) {
    for (j = 0; j < col; j++) {
        arr[i][j] = i;
        printf("arr[%d][%d] : %d\n",i,j,arr[i][j]);
    }
  }

  return 0;
}

Previous references:

Dynamic 2D array Pointer:

C programming initialize 2D array dynamically

Pointer to dynamic 2D array, But the explanation here is using new keyword and I want to use malloc instead:

How to allocate a 2D array of pointers in C++

Additional Info:

Consider following scenario:

XYZ* arr[A][B];

"XYZ" is a custom datatype, "A" & "B" are dynamic variables at runtime

In this case, how can we define A & B at runtime and access arr[A][B] element values using XYZ* type.

11
  • For a pointer to arr you need to become a three-star programmer, and being called that is usually not a compliment. Commented Sep 29, 2016 at 7:45
  • What's a "dynamic array"? An array which is allocated in dynamic memory or an array that have variable dimensions that may change at any time? The correct answer depends a lot on which of these you want. Commented Sep 29, 2016 at 7:45
  • 2
    In case you are merely looking to allocate a 2D array dynamically, then it should be int (*arr)[row] = malloc(sizeof(int[col][row])); And that's it. No pointer-to-pointer-to-pointer-to-pointers are needed... Commented Sep 29, 2016 at 7:47
  • Why do you need a triple-star pointer? What is the actual problem you try to solve by using one? If you want a dynamic array of arrays (which a pointer-to-pointer really isn't) then you already have it. Why do you need to add another level of indirection? Commented Sep 29, 2016 at 8:45
  • Please find the added additional info in the question. Commented Sep 29, 2016 at 10:24

2 Answers 2

1

Further down the answer, you find more possible solutions.

First, I want to present a solution to you, where you manage a dynamic 2d array with a 1d pointer, in case of same-length columns.

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

struct XYZ
{
    int someValue;
};

struct XYZ* GetArrayItem(struct XYZ* itemArray, int numCols, int row, int col)
{
    return &itemArray[row * numCols + col];
}

int main()
{
    int A = 5;
    int B = 4;
    struct XYZ* arr = (struct XYZ*)calloc(A*B, sizeof(struct XYZ));

    for (int i = 0; i < A; i++)
    {
        for (int j = 0; j < B; j++)
        {
            GetArrayItem(arr, B, i, j)->someValue = 1;
        }
    }

    free(arr);

    return 0;
}

With columns of different length, a double pointer might be a viable solution.

struct XYZ
{
    int someValue;
};

int main()
{
    int i;
    int j;
    // row count
    int A = 5;
    // column count per row
    int B[] = { 3, 4, 3, 2, 4 };
    struct XYZ** arr = (struct XYZ**)calloc(A, sizeof(struct XYZ*));
    for (i = 0; i < A; i++)
    {
        // initialize column for each row
        arr[i] = (struct XYZ*)calloc(B[i], sizeof(struct XYZ));
    }

    for (i = 0; i < A; i++)
    {
        for (j = 0; j < B[i]; j++)
        {
            // access items
            arr[i][j].someValue = 1;
        }
    }

    for (i = 0; i < A; i++)
    {
        free(arr[i]);
    }

    free(arr);

    return 0;
}

However, I would advise you to create a more explicit object structure in case where you need 2d data. This makes the design more explicit and the column count per row more transparent.

struct XYZ
{
    int someValue;
};

struct MyDomainSpecificRow
{
    int numColumns;
    struct XYZ* myRowData;
};

int main()
{
    int i;
    int j;
    // row count
    int A = 5;
    // column count per row
    int B[] = { 3, 4, 3, 2, 4 };
    // 1d array of rows, each containing 1d array of cells
    struct MyDomainSpecificRow* arr = (struct MyDomainSpecificRow*)calloc(A, sizeof(struct MyDomainSpecificRow));

    for (i = 0; i < A; i++)
    {
        // initialize column for each row
        arr[i].numColumns = B[i];
        arr[i].myRowData = (struct XYZ*)calloc(B[i], sizeof(struct XYZ));
    }

    for (i = 0; i < A; i++)
    {
        for (j = 0; j < arr[i].numColumns; j++)
        {
            // access items
            arr[i].myRowData[j].someValue = 1;
        }
    }

    for (i = 0; i < A; i++)
    {
        free(arr[i].myRowData);
    }

    free(arr);

    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

0

Solution: At last, I managed to get what I was looking for.

Declaration:

NodeClass* currentNode;     //Single Pointer Declaration
NodeClass*** triplePtrNode; //Triple Pointer Declaration

Definition & Allocation:

//row, col are dynamic values at runtime

//row memory allocation
triplePtrNode = (NodeClass***)malloc(sizeof(NodeClass)*row); 
for (i=0; i<row; ++i){
    //col memory allocation
    triplePtrNode[i] = (NodeClass**)malloc(sizeof(NodeClass)*col); 
}

Usage:

for (i=0; i<memberCounts; ++i){
    *(*(triplePtrNode+i)+0) = currentNode->member1;
    *(*(triplePtrNode+i)+1) = currentNode->member2;
}

3 Comments

There is no correct usage of triple pointers in C or C++. They are only useful in the branch of tree star programming. Rather than trying to become a tree star programmer, you should focus on solving the actual problem. There's a very big chance that you have chosen the wrong solution for the task.
Yes, I agree. I would like to add the following to your comment: MISRA-C:2004 17.5 "The declaration of objects should contain no more than 2 levels of pointer indirection" MISRA C++ 2008 5-0-19 The declaration of objects shall contain no more than two levels of pointer indirection.
2D arrays using an array of pointers to 1D arrays are much less efficient than 1D arrays with some arithmetics to do proper indexing. There is also no guarantee that the memory will be layed out consecutively, which might be an issue as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.