0

I know that one way to declare a pointer to a 2d array is like this:

int(*p)[100];

Then after assigning it to something, I can use elements like this:

p[1][6] = 18;

But let's say I don't yet know the dimensions of the array and I intend to malloc them when I find out.

One solution is that I declare a pointer to just an int, then use pointer arithmetic to navigate the array. I usually do this, but this time I'd like to use the square bracket notation for convenience.

So how do I declare this pointer when I don't yet know the dimensions and I intend to use square bracket notation?

Korgan Rivera
  • 495
  • 3
  • 9
  • 1
    There are arrays of arrays, and arrays of pointers. You can use the latter to navigate a 2D-array-like structure without knowing the dimensions beforehand. You cannot use the former in C89, because you cannot even mention its type without knowing at least the inner dimension. In C99 and beyond you can use VLAs but they have their limitations. – n. m. could be an AI Oct 14 '15 at 17:00
  • Possible duplicate of [Allocate memory 2d array in function C](http://stackoverflow.com/questions/15062718/allocate-memory-2d-array-in-function-c) – cadaniluk Oct 14 '15 at 17:06
  • @n.m.: `int (*p)[CONSTANT_LENGTH]` is a normal pointer to array, not a VLA or similar, so why would that not be C89 compliant (left aside that using C99 or C11 is a good idea in general)? Note that it is different from an array of pointers: `int *p[CONSTANT_DIM]`. – too honest for this site Oct 14 '15 at 17:09
  • @Olaf it is of course compliant, but one needs to know CONSTANT_LENGTH beforehand, which is not what OP requested. – n. m. could be an AI Oct 14 '15 at 17:14
  • @n.m.: Sorry, I just read `dimension`, not the plural. Defining a pointer to VLA should work, however. – too honest for this site Oct 14 '15 at 17:16
  • @n.m.: Why not use your 1st comment as an answer? – alk Oct 14 '15 at 18:20

4 Answers4

3

So how do I declare this pointer when I don't yet know the dimensions and I intend to use square bracket notation?

You can use a pointer to a pointer.

int** p = NULL;

and later....

p = malloc(N*sizeof(int*));
for (int i = 0; i < N; ++i )
{
   p[i] = malloc(M*sizeof(int));
}

and make sure to deallocate in multiple steps.

for (int i = 0; i < N; ++i )
{
   free(p[i]);
}
free(p);

Another way.

// Allocate memory for the pointers.
p = malloc(N*sizeof(int*));

// Allocate memory for the ints.
p[0] = malloc(M*N*sizeof(int));

// Assign the values to the elements of p.
for (int i = 1; i < N; ++i )
{
   p[i] = p[i-1] + M;
}

and deallocate in only two steps.

free(p[0]);
free(p);
R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

Simply use a pointer to a variable length array.

Your sizes, y rows with x elements:

size_t x = 123;
size_t y = 30;

Allocate in with one call, sizeof(*p) is identical to sizeof(int) * 123:

int (*p)[x] = malloc( sizeof(*p) * y );

And iterate the 2d array:

for( size_t i = 0 ; i < y ; i++ )
    for( size_t j = 0 ; j < x ; j++ )  
        p[i][j] = 0;
this
  • 5,229
  • 1
  • 22
  • 51
  • Note there was a discussion if you may use `sizeof(*vla)` before the pointer has been initialised. While I agree this is allowed, the standard's text might be missleading. This can be avoided by explicitly using `sizeof(int) * x * y)`. – too honest for this site Oct 14 '15 at 17:22
  • @Olaf So you are saying that the pointer should be initialized to avoid that ub, but the dereference isn't a problem? – this Oct 14 '15 at 17:41
  • http://stackoverflow.com/questions/32985424/is-the-operand-of-sizeof-evaluated-with-a-vla/32985668#comment53896597_32985668 I do not support the accepted answer, but that of Keith Thompson. Please read the comments, too. – too honest for this site Oct 14 '15 at 17:50
  • @Olaf I did. Compilers will do what Keith concludes at the end, but the Standard is still ambiguous in my opinion. Should we seriously start writing sizeof( int[y][x] ) just to be sure? – this Oct 14 '15 at 17:57
0
int(*p)[100];

This is not you want . This is pointer to array of int.

What you want is pointer to pointer to int.

int **p;
p=malloc(sizeof(int *)*r);       // allocate memory for r number of int *
for(int i=0;i<r;i++)
    p[i]=malloc(sizeof(int)*c);  //  allocate memory to each pointer  

free in similar manner.

ameyCU
  • 16,489
  • 2
  • 26
  • 41
-1

To index an array of arrays rather than an array of pointers, you can use this trick:

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

void f( const size_t m, const size_t n, const char s[m][n] )
{
   printf( "%s, %s!\n", s[0], s[1] );
   return;
}

int main(void) {
    static const char hello[][6] = { "hello", "world" };
    f( sizeof(hello)/sizeof(hello[0]), sizeof(hello[0]), hello );

    return EXIT_SUCCESS;
}

Your question is tagged C and not C++, but C++ does have references to arrays: int (&foo)[m][n] = bar;

Davislor
  • 14,674
  • 2
  • 34
  • 49