简体   繁体   中英

Whats the best way to declare pointers for 2D arrays in C?

I can't seem to find what I'm looking for. I'm learning how to use 2D Arrays in C while also learning pointers. Whats the best way to declare a pointer for a 2D array?

I'm doing it this way

    int nums[2][3] = {
            {5, 4, 3},
            {3, 0, 9}
    };
    int *numsptr = nums;
    printf("%p\n", numsptr);

Also how can I access specific indexes through pointers? The article I read said this.

In general, nums[i][j] is equivalent to *(*(nums+i)+j)

I tried doing this.

printf("%d\\n", (*numsptr + 1) + 2);

Which outputs 8 (Which isn't in the 2D array)

This is how I generally would

numsptr[r*cols + c]

Which would be equivalent to

nums[r][c]

If you want to dynamically find cols rather than hardcode, the following expression can be used

sizeof(nums[0])/sizeof(nums[0][0])

The reason this

printf("%d\n", (*numsptr + 1) + 2);

prints 8 is because *numsptr returns the value at nums[0] , which is 5 , adds 1 , and then adds 2 (which is 8 );

how can I access specific indexes through pointers?

Depends on the pointer. You can declare a pointer to an array of 3 ints , that way you can just access the pointer almost as-if the array (but watch out for sizeof ):

int (*ptr)[3] = nums;
for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
       printf("[%d][%d] = %d\n", i, j, ptr[i][j]);
       // since you mentioned `a[b] == *(a + b)` some alternatives:
       // or printf("[%d][%d] = %d\n", i, j, *(*(ptr + i) + j));
       // or printf("[%d][%d] = %d\n", i, j, *(ptr[i] + j));
       // or printf("[%d][%d] = %d\n", i, j, (*(ptr + i))[j]);
       // or pls dont printf("[%d][%d] = %d\n", i, j, i[ptr][j]);
    }
}

You use a pointer to the array of 2 arrays of 3 int s. Semantically, it's a different thing and you have to first dereference the pointer:

int (*var)[2][3] = &nums;
for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
        printf("[%d][%d] = %d\n", i, j, (*var)[i][j]);
    }
}

Because elements in an array are laid in memory continuously, you can alias the array with a pointer to int and do the row/column arithmetic yourself:

int *p = (int*)nums;
for (int i = 0; i < 2 * 3; ++i) {
    printf("[%d] = %d\n", i, p[i]);
}
for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
        printf("[%d][%d] = %d\n", i, j, p[i * 3 + j]);
    }
}

There are several flavors of pointers to multidimensional arrays.

There's the pointer that comes from applying the & operator to the array expression. Given the declaration

int nums[2][3];

then the expression &nums yields a pointer of type int (*)[2][3] - “pointer to 2-element array of 3-element array of int ”. You'd declare it as

int (*ptr)[2][3] = &nums;

You'd index into it as (*ptr)[i][j] . Since the [] operator has higher precedence than the unary * operator, you need to explicitly group the * with ptr for it to work properly.

There's the pointer that comes from the “decay” rule for arrays - except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type “N-element array of T ” will be converted (“decay”) to an expression of type “pointer to T ” and the value of the expression will be the address of the first element of the array. So the expression nums “decays” from type “2-element array of 3-element array of int ” ( int [2][3] ) to type “pointer to 3-element array of int ” ( int (*)[3] ):

int (*ptr)[3] = nums; // no & operator

You'd index into this as ptr[i][j] . Remember that the subscript operation a[i] is defined as *(a + i) , so *ptr is the same as ptr[0] , so (*ptr)[j] is the same as (ptr[0])[j] . This is probably the more commonly used form for pointers to 2D arrays.

Then there's the double pointer int ** , which is not actually a pointer to a 2D array, but a pointer to an array of pointers, each element of which points to the first element of another array, usually allocated like so:

int **ptr = malloc( 2 * sizeof *ptr );
if ( ptr )
{
  for ( size_t i = 0; i < 2; i++ )
  {
    ptr[i] = malloc( 3 * sizeof *ptr[i] );
  }
}

This is an example of a “jagged” array, where the rows are not contiguous and don't have to be the same size. These are usually allocated dynamically. You'd index into it as ptr[i][j] .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM