0

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 outputs8(Which isn't in the 2D array)

3
  • Also doing int *numsptr = &nums; doesn't change anything. Commented Feb 29, 2020 at 22:50
  • For a 2D array you need an int** pointer, not int* which is just 1D. Commented Feb 29, 2020 at 22:58
  • ((*numsptr + 1) + 2) that you are using is not the same as the article indicated which would be *(*(numsptr + 1) + 2) Commented Feb 29, 2020 at 22:59

3 Answers 3

1

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);

Sign up to request clarification or add additional context in comments.

1 Comment

Just as a note, in this particular case that's probably right, but that assumes a lot about how the structure is laid out internally. int* nums[2] could be a whole different thing even if superficially similar.
1

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 ints. 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]);
    }
}

Comments

1

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].

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.