How to Assign Two Dimensional Array to **Pointer

how to assign two dimensional array to **pointer ?

The simple answer is that you cannot. A bidimensional array is a contiguous block of memory that holds each line, while a pointer to pointer can refer to a memory location where a pointer to a different memory location containing the integers is.

You can on the other hand create a separate data structure that holds the pointers to the elements in the way you want (i.e. create an array of pointers, initialize those pointers to the beginning of each row, and use a pointer to that array of pointers as pointer), but it is not useful at all, but rather will complicate everything unneedingly.

The question probably comes from the common misconceptions that arrays and pointers are the same, which they are not. An array can decay to a pointer to the first element of the array (and will do so quite often), but the type of that pointer is the type of the first element. In a bidimensional array, the type of the first element is the inner array, not the basic element type.

Create a pointer to two-dimensional array

Here you wanna make a pointer to the first element of the array

uint8_t (*matrix_ptr)[20] = l_matrix;

With typedef, this looks cleaner

typedef uint8_t array_of_20_uint8_t[20];
array_of_20_uint8_t *matrix_ptr = l_matrix;

Then you can enjoy life again :)

matrix_ptr[0][1] = ...;

Beware of the pointer/array world in C, much confusion is around this.


Edit

Reviewing some of the other answers here, because the comment fields are too short to do there. Multiple alternatives were proposed, but it wasn't shown how they behave. Here is how they do

uint8_t (*matrix_ptr)[][20] = l_matrix;

If you fix the error and add the address-of operator & like in the following snippet

uint8_t (*matrix_ptr)[][20] = &l_matrix;

Then that one creates a pointer to an incomplete array type of elements of type array of 20 uint8_t. Because the pointer is to an array of arrays, you have to access it with

(*matrix_ptr)[0][1] = ...;

And because it's a pointer to an incomplete array, you cannot do as a shortcut

matrix_ptr[0][0][1] = ...;

Because indexing requires the element type's size to be known (indexing implies an addition of an integer to the pointer, so it won't work with incomplete types). Note that this only works in C, because T[] and T[N] are compatible types. C++ does not have a concept of compatible types, and so it will reject that code, because T[] and T[10] are different types.


The following alternative doesn't work at all, because the element type of the array, when you view it as a one-dimensional array, is not uint8_t, but uint8_t[20]

uint8_t *matrix_ptr = l_matrix; // fail

The following is a good alternative

uint8_t (*matrix_ptr)[10][20] = &l_matrix;

You access it with

(*matrix_ptr)[0][1] = ...;
matrix_ptr[0][0][1] = ...; // also possible now

It has the benefit that it preserves the outer dimension's size. So you can apply sizeof on it

sizeof (*matrix_ptr) == sizeof(uint8_t) * 10 * 20

There is one other answer that makes use of the fact that items in an array are contiguously stored

uint8_t *matrix_ptr = l_matrix[0];

Now, that formally only allows you to access the elements of the first element of the two dimensional array. That is, the following condition hold

matrix_ptr[0] = ...; // valid
matrix_ptr[19] = ...; // valid

matrix_ptr[20] = ...; // undefined behavior
matrix_ptr[10*20-1] = ...; // undefined behavior

You will notice it probably works up to 10*20-1, but if you throw on alias analysis and other aggressive optimizations, some compiler could make an assumption that may break that code. Having said that, i've never encountered a compiler that fails on it (but then again, i've not used that technique in real code), and even the C FAQ has that technique contained (with a warning about its UB'ness), and if you cannot change the array type, this is a last option to save you :)

Declaring a pointer to multidimensional array and allocating the array

I just found this ancient answer still gets read, which is a shame since it's wrong. Look at the answer below with all the votes instead.


Read up on pointer syntax, you need an array of arrays. Which is the same thing as a pointer to a pointer.

int width = 5;
int height = 5;
int** arr = new int*[width];
for(int i = 0; i < width; ++i)
arr[i] = new int[height];

Assigning value to two dimensional array with the use of pointers C++

you can do

#include <iostream> 
using namespace std;
int main(void) {
int matrix[11][11] = {};

for(int i = 1; i <= 10; i++) {
for(int j = 1; j <= 10; j++) {
*(*(matrix + i - 1) + j - 1) = i * j;
}
}

for(int i = 0; i < 10; i++) {
for(int j = 0; j < 10; j++) {
cout.width(4);
cout << matrix[i][j]; }

cout << endl;
}
}

int[][] can be used as int**

so matrix can be treated as an int**
and *(matrix + i) is the same thing as matrix[i]

conversion of 2D array to pointer-to-pointer

A mere conversion won't help you here. There's no compatibility of any kind between 2D array type and pointer-to-pointer type. Such conversion would make no sense.

If you really really need to do that, you have to introduce an extra intermediate "row index" array, which will bridge the gap between 2D array semantics and pointer-to-pointer semantics

Activity solution[a][b];

Activity *solution_rows[a] = { solution[0], solution[1] /* and so on */ };

Activity **mother = solution_rows;

Now accessing mother[i][j] will give you access to solution[i][j].

pointer to a 2 dimensional array

Why i have to cast the balance with a (float *) ?

This is because p is of type float * while balance is of type float (*)[5] after decaying to the pointer.

is this because the array is 2 dimensions?

Yes.

so the pointer is also 2 dimensions?

balance decays to float (*)[5].

so i have to transform it to a 1 dimension ?

Yes.

The correct way to initialize a dynamic pointer to a multidimensional array?

Let's start with some basic examples.

When you say int *P = new int[4];

  1. new int[4]; calls operator new function()
  2. allocates a memory for 4 integers.
  3. returns a reference to this memory.
  4. to bind this reference, you need to have same type of pointer as that of return reference so you do

    int *P = new int[4]; // As you created an array of integer
    // you should assign it to a pointer-to-integer

For a multi-idimensional array, you need to allocate an array of pointers, then fill that array with pointers to arrays, like this:

int **p;
p = new int*[5]; // dynamic `array (size 5) of pointers to int`

for (int i = 0; i < 5; ++i) {
p[i] = new int[10];
// each i-th pointer is now pointing to dynamic array (size 10)
// of actual int values
}

Here is what it looks like:

Sample Image

To free the memory

  1. For one dimensional array,

     // need to use the delete[] operator because we used the new[] operator
    delete[] p; //free memory pointed by p;`
  2. For 2d Array,

    // need to use the delete[] operator because we used the new[] operator
    for(int i = 0; i < 5; ++i){
    delete[] p[i];//deletes an inner array of integer;
    }

    delete[] p; //delete pointer holding array of pointers;

Avoid memory leakage and dangling pointers!

Pointer-to-pointer dynamic two-dimensional array

The first method cannot be used to create dynamic 2D arrays because by doing:

int *board[4];

you essentially allocated an array of 4 pointers to int on stack. Therefore, if you now populate each of these 4 pointers with a dynamic array:

for (int i = 0; i < 4; ++i) {
board[i] = new int[10];
}

what you end-up with is a 2D array with static number of rows (in this case 4) and dynamic number of columns (in this case 10). So it is not fully dynamic because when you allocate an array on stack you should specify a constant size, i.e. known at compile-time. Dynamic array is called dynamic because its size is not necessary to be known at compile-time, but can rather be determined by some variable in runtime.

Once again, when you do:

int *board[4];

or:

const int x = 4; // <--- `const` qualifier is absolutely needed in this case!
int *board[x];

you supply a constant known at compile-time (in this case 4 or x) so that compiler can now pre-allocate this memory for your array, and when your program is loaded into the memory it would already have this amount of memory for the board array, that's why it is called static, i.e. because the size is hard-coded and cannot be changed dynamically (in runtime).

On the other hand, when you do:

int **board;
board = new int*[10];

or:

int x = 10; // <--- Notice that it does not have to be `const` anymore!
int **board;
board = new int*[x];

the compiler does not know how much memory board array will require, and therefore it does not pre-allocate anything. But when you start your program, the size of array would be determined by the value of x variable (in runtime) and the corresponding space for board array would be allocated on so-called heap - the area of memory where all programs running on your computer can allocate unknown beforehand (at compile-time) amounts memory for personal usage.

As a result, to truly create dynamic 2D array you have to go with the second method:

int **board;
board = new int*[10]; // dynamic array (size 10) of pointers to int

for (int i = 0; i < 10; ++i) {
board[i] = new int[10];
// each i-th pointer is now pointing to dynamic array (size 10) of actual int values
}

We've just created an square 2D array with 10 by 10 dimensions. To traverse it and populate it with actual values, for example 1, we could use nested loops:

for (int i = 0; i < 10; ++i) {   // for each row
for (int j = 0; j < 10; ++j) { // for each column
board[i][j] = 1;
}
}

Not able to access two dimensional array by assigning to pointer

Are you trying to build a function which takes in a two-dimensional pointer (have to be two-dimensional) along with its dimensions and printing out its contents?

You need to known that a pointer to a pointer is not the same as a 2D array aka array of arrays. You must know that C does not really have two-dimensional or higher-dimensional arrays: they are just arrays of arrays. Dynamic memory should be used if you want the 2D array to be a pointer to a pointer. See How to pass 2D array (matrix) in a function in C? to get how to pass in a 2D array and then printing out the result.

I also don't fully understand your code. In your code, you claimed that it works for 1D arrays, but it does not work for 2D arrays. However, your code don't use row or col at all, but rather generate a preset 1D and 2D arrays.

Additionally, you cannot overload C functions. Therefore, printOutput either supports 1D or 2D arrays. Here is my sample code which works for 2D arrays along with a sample input-output:

void printOutput(int row, int col, int array[row][col])
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%d ", array[i][j]);
}
printf("\n");
}
printf("\n");
}

int main() {
int m1[2][2] = {{1,2},{-2,0}};
int m2[3][3] = {{1,5,6},{3,2,7},{8,4,9}};
int m3[2][5] = {{0,1,2,3,4},{5,6,7,8,9}};
int m4[1][7] = {{-3,-2,-1,0,1,2,3}};

printOutput(2, 2, m1);
printOutput(3, 3, m2);
printOutput(2, 5, m3);
printOutput(1, 7, m4);
return 0;
}

The output would be:

1 2                                                                                                                              
-2 0

1 5 6
3 2 7
8 4 9

0 1 2 3 4
5 6 7 8 9

-3 -2 -1 0 1 2 3

Pointer to 2D arrays in C

//defines an array of 280 pointers (1120 or 2240 bytes)
int *pointer1 [280];

//defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
int (*pointer2)[280]; //pointer to an array of 280 integers
int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers

Using pointer2 or pointer3 produce the same binary except manipulations as ++pointer2 as pointed out by WhozCraig.

I recommend using typedef (producing same binary code as above pointer3)

typedef int myType[100][280];
myType *pointer3;

Note: Since C++11, you can also use keyword using instead of typedef

using myType = int[100][280];
myType *pointer3;

in your example:

myType *pointer;                // pointer creation
pointer = &tab1; // assignation
(*pointer)[5][12] = 517; // set (write)
int myint = (*pointer)[5][12]; // get (read)

Note: If the array tab1 is used within a function body => this array will be placed within the call stack memory. But the stack size is limited. Using arrays bigger than the free memory stack produces a stack overflow crash.

The full snippet is online-compilable at gcc.godbolt.org

int main()
{
//defines an array of 280 pointers (1120 or 2240 bytes)
int *pointer1 [280];
static_assert( sizeof(pointer1) == 2240, "" );

//defines a pointer (4 or 8 bytes depending on 32/64 bits platform)
int (*pointer2)[280]; //pointer to an array of 280 integers
int (*pointer3)[100][280]; //pointer to an 2D array of 100*280 integers
static_assert( sizeof(pointer2) == 8, "" );
static_assert( sizeof(pointer3) == 8, "" );

// Use 'typedef' (or 'using' if you use a modern C++ compiler)
typedef int myType[100][280];
//using myType = int[100][280];

int tab1[100][280];

myType *pointer; // pointer creation
pointer = &tab1; // assignation
(*pointer)[5][12] = 517; // set (write)
int myint = (*pointer)[5][12]; // get (read)

return myint;
}


Related Topics



Leave a reply



Submit