0

Good day guys! I am learning C and quite messed up now as I go through pointer and arrays.

1)Why can't I have a 2D array of int type using pointers? Like

int *arr[4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};

or

int **arr = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};

Seems quite convincible to me though...

  1. Also, why we use char * arr[5] in replace of char arr[5][40] instead of char * arr[40], that simply could not make sense to me...

Many thanks to your guys in advance!

Larry1024
  • 11
  • 3
  • 2
    You can have an array of pointers, each pointing to an array... or you can have a pointer to array, pointing at an array of arrays. The two are not the same, though. – Dmitri Jul 03 '20 at 03:23
  • `int arr[3][4]` is what you want. – Ken Y-N Jul 03 '20 at 03:24
  • int arr[][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12} }; will work as well – Paul Baxter Jul 03 '20 at 03:29
  • `int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};` will make `arr` a 3-element array of 4-element arrays of `int`. `int (*pArr)[4] = arr;` will make `pArr` a pointer to 4-element arrays of `int` that points at `arr`. – Dmitri Jul 03 '20 at 03:48
  • Hi @Dmitri! I see what you mean! Coz I see we can do that for array of strings, so I am wonder why we cannot have that for simple 2D arrays – Larry1024 Jul 03 '20 at 03:50
  • You *can*... `int (*arr)[4];` is a pointer to arrays of `int`, and can be used for a 2D array -- just watch the parentheses -- `int (*arr)[4]` is not the same as `int *arr[4]`. – Dmitri Jul 03 '20 at 04:03
  • Or `int *arr[3]` will give you an array of pointers, and you can point each one at a 1D array of `int` -- that's actually closer to what happens when you use eg. `char *arr[3]` for a group of strings (which is not a 2D `char` array but a 1D pointer array, with each element pointed to a 1D `char` array) – Dmitri Jul 03 '20 at 04:10
  • Thank you @Dmitri! You are really helpful! – Larry1024 Jul 03 '20 at 06:03

2 Answers2

1

Pointers are not arrays and arrays are not pointers. A pointer can however be used to point at the first element in an array.

You need to make up your mind if you wish to have a 2D array of int or a 1D array of int*, each pointing the first element of an array.


A 2D array is simply:

int arr[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};

This is the fastest form you'll ever get, but it is restricted to the scope it is allocated inside.


A 1D array of pointers to first elements can be done by having the pointers point at local scope arrays:

int* arr [3] = {(int[]){1,2,3,4}, (int[]){5,6,7,8}, (int[]){9,10,11,12}};

This is utilizing the feature known as compound literals. These arrays will have the same scope as arr and go out of bounds when arr does.


If you need the arrays to stay alive outside that scope, you could use dynamic memory allocation instead:

int (*arr)[4] = malloc( sizeof(int[3][4]) );
...
arr[i][j] = something;
...
free(arr);

The above creates a dynamically allocated 2D array, then lets an array pointer point at the first array inside that 2D array.


It's also possible to create slower, crappier code by dynamically allocating a 1D array of int* then have each pointer point at the first element of an array:

int** arr = malloc( sizeof(int*[3]) );
for(size_t i=0; i<3; i++)
{
  arr[i] = malloc( sizeof(int[4]) );
}

...

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

This amateur form has absolutely no advantage in your case. Code like the above only makes sense when we need completely variable-sized dimensions, which we don't in case of static 2D arrays.

So all this version does is to segment the heap and block data cache utilization, wasting memory and execution speed. You also need to free() it in several steps, with a loop.

More info: Correctly allocating multi-dimensional arrays

Lundin
  • 195,001
  • 40
  • 254
  • 396
0

Correctly said by @Dmitri.

You can have an array of pointers, each pointing to an array... or you can have a pointer to array, pointing at an array of arrays.

Example:

int r = 3, c = 4;

int **arr = (int **)malloc(r * sizeof(int *)); 
for (int i=0; i<r; i++) 
     arr[i] = (int *)malloc(c * sizeof(int)); 

After initialising, you can assign the values.

Deepak Tatyaji Ahire
  • 4,883
  • 2
  • 13
  • 35
  • Hi Deepak! Thank you for clarifying! Its just I see we can do that for array of strings(using char ar*[5] to replace char ar[5][40]), so I am wonder why we cannot have that for simple 2D arrays – Larry1024 Jul 03 '20 at 03:53