How to Allocate a 2D Array of Pointers in C++

Pointer to a 2D dynamic Array Pointer

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;
}

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

By the letter of the law, here's how to do it:

// Create 2D array of pointers:
int*** array2d = new (int**)[rows];
for (int i = 0; i < rows; ++i) {
array2d[i] = new (int*)[cols];
}

// Null out the pointers contained in the array:
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
array2d[i][j] = NULL;
}
}

Be careful to delete the contained pointers, the row arrays, and the column array all separately and in the correct order.

However, more frequently in C++ you'd create a class that internally managed a 1D array of pointers and overload the function call operator to provide 2D indexing. That way you're really have a contiguous array of pointers, rather than an array of arrays of pointers.

How to allocate a 2D array of pointers to a struct

Technically speaking, this won't create 2D array. The result will be array of pointers, where each one points to different array of pointers to a struct.

The difference is that, memory will be fragmented, so every element will point to some memory location, instead of single continuous memory block.

The common approach for this is to create flatten 2D array:

flightInfo** allocateMatrix(int n)
{
flightInfo** matrix = malloc(n*n * sizeof(*matrix));
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
matrix[i*n + j] = NULL;
return matrix;
}

If you are forced to use two indices, then you could place matrix as function argument:

void allocateMatrix(int n, flightInfo* (**matrix)[n])
{
*matrix = malloc(n * sizeof(**matrix));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
(*matrix)[i][j] = NULL;
}

The second asterisk is required, because pointers are passed by value, otherwise you would end up with modified local copy of the pointer, that does nothing to matrix from main function.

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

typedef struct flightInfo {
char airport[30];
int altitude;
} flightInfo;

void allocateMatrix(int n, flightInfo* (**matrix)[n])
{
*matrix = malloc(n * sizeof(**matrix));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
(*matrix)[i][j] = NULL;
}

int main()
{
int n = 10;
flightInfo* (*matrix)[n];

allocateMatrix(n, &matrix);

matrix[0][0] = malloc(sizeof(flightInfo));
strcpy(matrix[0][0]->airport, "Heathrow");
matrix[0][0]->altitude = 10000;

printf("%s, %d\n", matrix[0][0]->airport, matrix[0][0]->altitude);
}

The another way would be to encapsulate the array within a struct.

Is a 2D Array an Array of Pointers?

The way you have defined A means that the compiler will allocate for it a contiguous block of memory large enough to hold 10 x 20 (200) integers; see here (scroll down to "Multidimesional arrays"). As I'm sure you realize, if you were to do printf("%p", A); you would see the address of the beginning of that allocated block.

Now, when the compiler sees the expression A[3], it will add what it calculates as the necessary amount of "integer sizes" to the base address (that of A, or A[0][0]); in this case, it will add "3" (the index specified) multiplied by the combined size of all the other dimensions (in this case, there's only one, which is 20).

So, in your case, there is no actual array of pointers; just a memory block that the compiler can interpret according to how you described any part(s) of it.

However, in a more versatile approach, one can actually define a 2D array in terms of an actual array of pointers, like so:

int **A;
A = malloc(10 * sizeof(int*));
for (int n = 0; n < 10; ++n) A[n] = malloc(20 * sizeof(int));

In this case, using printf("%p",A[3]); would still be valid, but it would give a very different offset value from printf("%p",A); or printf("%p",A[0]);.

It's also, perhaps, worth noting that, even though these two different declarations for A can both resolve an individual element through an expression like A[i][j] (but the compiler would evaluate the addresses differently), there is here scope for major confusion! When, for example, passing such an array to a function: if the function expects data allocated in the second form, and you give it an array defined in the first form (and vice versa), you're gonna get major undefined behaviour .

Problems with pointers and 2D - arrays (dynamic allocation of memory)

There are at least two problems with the provided code. :

  • You are passing a **int variable as first parameter of read_matr, but this function is requesting a ***int parameter (a pointer to a 2dimensional array). The parameter seems correct, but then you need to pass a pointer to your array in this way:

    int n = read_matr(&m, f);
  • Your array is supposed to be 2d dimensional, but you are only allocating it as a 1dimensional array. After allocating a first array, you need to allocate each row independently:

    *m = (int **) malloc(length * sizeof(int*));
    for(i=0; i<length; ++i) {
    (*m)[i] = (int*) malloc(length * sizeof(int));
    ...
    }

Optionally, you can make a 1dimensionnal array of size length*length, and then you would access m[i][j] by m[i * length + j]

Warnings could have helped you a great deal there.

How to dynamically allocate and deallocate a 2D array using pointers in c++?

When you need to pass reference or by pointer, when given the opportunity, it's better to pass by reference.

A pointer can take null arguments, a reference can't, it's safer to use, unless, for some reason, you specifically need to pass null arguments which I believe is not the case.

Note that you're accessing uninitialized memory when you print the array.

Also note that despite using boolean flag to signal allocation errors you're code still is vulnerable, a better way to do this would be to use std::exception.

bool allocateTwoDimTable(int** &table, int sizeX, int sizeY) {
if (sizeX <= 0 || sizeY <= 0) return false;

// allocate 2D table
table = new int* [sizeX];

for (int i = 0; i < sizeX; i++) {
table[i] = new int[sizeY];
}

cout << endl << "Table " << sizeX << " x " << sizeY << endl;
for (int i = 0; i < sizeX; i++) {
cout << endl;
for (int j = 0; j < sizeY; j++) {
table[i][j] = i + j; //initializing elements of the array
cout << table[i][j] << ", ";
}
}

return true;
}
bool deallocateTwoDimTable(int (** &table), int sizeX) {
if (sizeX <= 0) return false;

for (int k = 0; k < sizeX; k++) {
delete[] table[k];
}

delete[] table;

return true;
}
int main() {

int** table = nullptr;

const int sizeX = 5; // rows
const int sizeY = 3; // columns

try {
const bool allocationResult = allocateTwoDimTable(table, sizeX, sizeY);
cout << endl << "allocation result: " << (allocationResult ? "true" : "false") << endl;

const bool deallocationResult = deallocateTwoDimTable(table, sizeX);
cout << endl << "deallocation result: " << (deallocationResult ? "true" : "false");
}
catch (std::exception& e)
{
std::cout << e.what();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

How can I dynamically allocate 2D-array in one allocate C

How can i to allocate dynamically array2D in 1 allocate C

Let us start with what is a 2D array:

Example of a 2D array or "array 3 of array 4 of int"

int arr1[3][4];
arr1[0][0] = this;

OP's code declares a pointer to pointer to int, not a 2D array nor a pointer to a 2D array.

BTW, the cast in not needed.

int** arr = (int**)malloc(num * num * sizeof(int*));

Code can allocate memory for a 2D array and return a pointer to that memory. pointer to array 5 of array 6 of int

 int (*arr2)[5][6] = malloc(sizeof *arr2);
if (arr2 == NULL) return EXIT_FAILURE;
(*arr2)[0][0] = this;
return EXIT_SUCCESS;

// or with Variable Length Arrays in C99 and optionally in C11
int (*arr3)[num][num] = malloc(sizeof *arr3);
(*arr3)[0][0] = that;

Alternatively code can allocate memory for a 1D array and return a pointer to that memory. pointer to array 8 of int. Sometimes this is often what one wants with with an "allocate 2D" array, really a pointer to a 1D array

 int (*arr4)[8] = malloc(sizeof *arr4 * 7);
arr4[0][0] = this;

// or
int (*arr5)[num] = malloc(sizeof *arr5 * num);
arr5[0][0] = that;

How C/C++ compiler distinguish regular two dimensional array and array of pointers to arrays?

For this declaration of an array

int a1[N][M] = { {0,1,2}, {3,4,5}, {6,7,8} };

these records

int x = a1[1][2];
int y = *(a1+2+N*1);

are not equivalent.

The second one is incorrect. The expression *(a1+2+N*1) has the type int[3] that is implicitly converted to an object of the type int * used as an initializer. So the integer variable y is initialized by a pointer.

The operator a1[1] is evaluated like *( a1 + 1 ) . The result is a one-dimensional array of the type int[3].

So applying the second subscript operator you will get *( *( a1 + 1 ) + 2 ).

The difference between the expressions when used the two-dimensional array and the dynamically allocated array is that the designator of the two-dimensional array in this expression (a1 + 1) is implicitly converted to a pointer to its first element of the type int ( * )[3] while the pointer to the dynamically allocated array of pointers still have the same type int **.

In the first case dereferencing the expression *(a1 + 1 ) you will get lvalue of the type int[3] that in turn used in the expression *( a1 + 1) + 2 is again implicitly converted to a pointer of the type int *.

In the second case the expression *(a1 + 1) yields an object of the type int *.

In the both cases there is used the pointer arithmetic. The difference is that when you are using arrays in the subscript operator then they are implicitly converted to pointers to their first elements.

When you are allocating dynamically arrays when you are already deals with pointers to their first elements.

For example instead of these allocations

int** a2 = new int*[N];
for (int i = 0; i < N; i++)
a2[i] = new int[M];

you could just write

int ( *a2 )[M] = new int[N][M];


Related Topics



Leave a reply



Submit