2

If I have array a, how would I set a pointer to the first row?

double a[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Sean Mabli
  • 37
  • 8
  • 1
    By "first", I assume you mean row 0. There are _two_ ways to get the address. And, two rows, so: `double *row0a = a[0]; double *row0b = &a[0][0]; double *row1a = a[1]; double *row1b = &a[1][0];` – Craig Estey Jun 30 '22 at 17:06

4 Answers4

2

You can declare a pointer to a row and initialize it to point to the first row with the following line:

double (*p_first_row)[4] = &a[0];

Due to array to pointer decay, you can also write:

double (*p_first_row)[4] = a;

The parentheses are necessary, because the declaration

double *p[4];

declares an array of pointers, whereas the declaration

double (*p)[4];

declares a pointer to an array.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • How do you save ```double (*p)[4]``` without the ```[4]```? – Sean Mabli Jun 30 '22 at 21:10
  • @SeanMabli: I don't understand your question. Please elaborate. What exactly do you mean with "save"? And what do you intend to accomplish by removing the `[4]`? – Andreas Wenzel Jun 30 '22 at 21:13
  • @SeanMabli: If you want `p` to be a "pointer to a row", then the type of `p` must be "pointer to an array of 4 elements, in which each element is of type `double`. Therefore, you must specify the dimension of the array in the declaration, if you want `p` to be a "pointer to a row". Although it is possible to strip the type information, for example by making `p` of type `void *` instead, you won't be able to use that pointer for anything, until you cast the pointer back to the proper type. – Andreas Wenzel Jun 30 '22 at 21:22
  • @SeanMabli: Maybe you don't want "a pointer to the first row", but rather "a pointer to the first element of the first row". In that case, you can simply write `double *p = a[0];`. You can then use the expression `p[0]` to access the first element of the first row, `p[1]` to access the second element of the first row, `p[2]` to access the third element of the first row, and `p[3]` to access the fourth element of the first row. Using these expressions is also possible if you define `p` like this: `double (*p)[4] = a;`, due to [array to pointer decay](https://stackoverflow.com/q/1461432). – Andreas Wenzel Jun 30 '22 at 21:33
  • @SeanMabli: It is important to understand that in C, when you write the name of an array in an expression, in most cases (including all cases described in this question), the array [decays](https://stackoverflow.com/q/1461432) (is transformed to) to a pointer to the first element of the array. – Andreas Wenzel Jun 30 '22 at 21:41
  • What I am trying to do is have a n-dimensional array and get the shape of it by recursively getting the sizeof() of the first row of every dimension. That is the reason why I don't want to specify the dimension when I save the output of this first row into a variable. Do you have any ideas of how to do this? – Sean Mabli Jun 30 '22 at 21:46
  • @SeanMabli: I have the impression that your original question is about an [XY problem](https://xyproblem.info/). In order to find the number of elements of an array `a`, you can use the expression `sizeof a / sizeof *a`. This also works with multi-dimensional arrays. It will give you the number of elements in the outer array. In order to find the number of elements in the second level of the array, you can use the expression `sizeof *a / sizeof **a`. – Andreas Wenzel Jun 30 '22 at 22:01
  • @SeanMabli: In order to find the number of elements in the third level of the array (assuming that there is one, which there isn't in your case), you can use the expression `sizeof **a / sizeof ***a`. – Andreas Wenzel Jun 30 '22 at 22:02
  • @SeanMabli: The expession `sizeof a / sizeof *a` works, because `sizeof a` is the total size of the array, whereas `sizeof *a` is the size of an individual element of the (outer) array. Dividing the total size of the array by the size of the individual elements of the array will give you the number of elements of the array. – Andreas Wenzel Jun 30 '22 at 22:05
  • @SeanMabli: In the case of `double a[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};`, the expression `sizeof a / sizeof *a` will probably give you `64 / 32`, which is `2`, which is the number of elements in the outer array. The expression `sizeof *a / sizeof **a` will probably give you `32 / 8`, which is `4`, which is the number of elements in the inner array. – Andreas Wenzel Jun 30 '22 at 22:08
  • But this doesn't work because you can't recursively go until you have a shape with the ```sizeof a / sizeof *a``` framwork. Unless you handcode ```sizeof a / sizeof *a```, ```sizeof *a / sizeof **a```. ```sizeof **a / sizeof ***a``` ... – Sean Mabli Jun 30 '22 at 22:11
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/246084/discussion-between-andreas-wenzel-and-sean-mabli). – Andreas Wenzel Jun 30 '22 at 22:13
1

If you have a multi-dimensional array like for example

T a[N1][N2][N3][N4];

where T is some type specifier and N1, N2, N3, N4 are some positive integers then to make a pointer to the first element of the array just change the left most dimension to asterisk like

T ( *p )[N2][N3][N4] = a;

In this declaration the array designator a is implicitly converted to a pointer to its first element.

If you want to get a pointer to the i-th (0 <= i < N1) element of the array (that is an array of the type T[N2][N3][N4]) you can write

T ( *p )[N2][N3][N4] = a + i;

or

T ( *p )[N2][N3][N4] = a;
p += i;

Here is a demonstration program.

#include <stdio.h>

int main( void )
{
    double a[2][4] = 
    {
        {1, 2, 3, 4}, 
        {5, 6, 7, 8}
    };

    for ( double ( *row )[4] = a; row != a + 2; ++row )
    {
        for ( double *p = *row; p != *row + 4; ++p )
        {
            printf( "%.1f ", *p );
        }

        putchar( '\n' );
    }
}

The program output is

1.0 2.0 3.0 4.0 
5.0 6.0 7.0 8.0 
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

Just dereference it normally as you would do to any pointer. *(a + 0) gives you the first row of the matrix, and *(a + i) will give you the i-th row in the 2D array.

A sample code to get the first element in each row of your 2d array would look like this.

double a[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};

for (int i = 0; i < 2; i ++) {
  printf("%lf ", *(a + i)[0]);
}

Output:

1 5
0
  • A 2D array in C is an array of arrays.
  • double a[2][4] = an array with size 2, each items of type double[4].
  • A pointer to such an array is declared as double (*p)[2][4] and initialized/assigned as p=&a.
  • Similarly, a pointer to an array of type double a[4] is declared as double (*p)[4].
  • Any array in C, whenever used in most expressions, "decays" into a pointer to its first element.
  • Since the first item of double a[2][4] has type double [4], then a will decay into a pointer to such an item, double (*)[4], whenever used in an expression.

Therefore we can iterate through the double a[2][4] like this, if we wish:

double a[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};

for(double (*p)[4]=a; p<a+2; p++)
{
   printf("%lf %lf %lf %lf\n", (*p)[0],(*p)[1],(*p)[2],(*p)[3]);
}

Which is also equivalent to double (*p)[4]=&a[0].


Now suppose that we write an expression some with saner syntax as we ought to:

a[i][j]

Any a[i] expression is by definition 100% equivalent to *(a+i). So the above is equivalent to *(*(a+i)+j).

Here pointer arithmetic is used twice: a+i is pointer arithmetic on a double(*)[4] type, increasing the address with i * sizeof(double[4]) bytes. Whereas the +j part is pointer arithmetic on a double*, increasing the address with j * sizeof(double) bytes.

Thus a[1][0] = (char*)a + 1 * sizeof(double[4]) + 0 * sizeof(double)

Example:

#include <stdio.h>

int main()
{
   double a[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}};
   printf("%lf ", a[1][0] );
   printf("%lf ", (char*)a + 1 * sizeof(double[4]) + 0 * sizeof(double) );
}
Lundin
  • 195,001
  • 40
  • 254
  • 396