2

What is the method for specifying a position in a 2D array. I do not mean getting the value through subscripting but in a way analogous to a 1D array where given a pointer it is possible to use a + operator and go to that position.

For instance if I have some array A of size 4, I can go to the third element by A + 2.

How would I do this when I have a 2D array?

Mars
  • 4,677
  • 8
  • 43
  • 65

7 Answers7

3

Where A is the array, R is the row, and C is the column.

*(A + R) + C

gives you the address of A[R][C]

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • That would works SOMETIMES, depending how the array was allocated. See my answer below. – Michael Sep 17 '13 at 20:12
  • 1
    @Michael: Unless you have a second account, you didn't post an answer. – Benjamin Lindley Sep 17 '13 at 20:15
  • Sorry, Benjamin, was too slow at the keyboard, it's in now. – Michael Sep 17 '13 at 20:20
  • @Michael: Your answer isn't wrong, but I don't think it addresses the question. I believe the question is about the correct syntax for a specific case, not best practices. – Benjamin Lindley Sep 17 '13 at 20:21
  • OK then, your answer (as well as a David's) is technically correct. I just prefer not to encourage bad practices by advising how to. If somebody would ask me "how should I drive stick shift blindfolded" I wouldn't start describing the gears and the clutch. – Michael Sep 17 '13 at 20:25
  • @Michael: It can be argued that `vector>` is not *best practice* either. It all depends on the problem at hand, but to represent a rectangular space I'd go for a class that wraps a single `vector` and using arithmetic... Without knowing the real problem to solve, I don't think you can recommend what the best solution would be. – David Rodríguez - dribeas Sep 17 '13 at 20:31
2

Yes you are correct. You can access the element by multiplying the row dimension to the column size and adding the column index.

Suppose your integer array is arr[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS], then you can access the arr[ROW_INDEX][COLUMN_INDEX] element as:

int num = *((int *)arr + ROW_INDEX * NUMBER_OF_COLUMNS + COLUMN_INDEX);
Saksham
  • 9,037
  • 7
  • 45
  • 73
1

The question is unclear, but here are some thoughts.

There are no multidimensional arrays in the language, only one dimensional arrays are supported, with some additional guarantees. What is commonly referred to as 2D array is a 1D array of objects of type array of the given type. The additional guarantees are those of contiguity and alignment: each element in the array is contiguous with the next element in the array, and the array and the first element are aligned.

Arrays have a tendency to decay to a pointer to the first element, and you can use pointer arithmetic to move to the next elements in the array, which is what allows the syntax A + 2 meaning: &A[0] + 2 or a pointer that is the result of adding 2 to the first (zero-th) element in the array. But the decay is only of the top level array.

The guarantees laid out before mean that you can use the array as if it was a pointer to the first element, and that element is in exactly the same location as the array itself. Applying this recursively to the nested array you can get to the following:

int array[10][10];
// array is an array of 10 arrays of 10 int
// array[0] is an array of 10 int, the first subarray
// array[0][0] is an int, the first element of the subarray
int *p = &array[0][0];
int *q = p + 10;           // One beyond the first subarray: pointer to the first
                           // element of the second subarray.
int *r = p + 10*row + col; // pointer to the col-th element inside the row-th subarray
                           // equivalent to &array[row][col]
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • My comment for Benjamin's answer applies here too: this will work only if you are confident that array was declared exactly like that and the declaration will never change. – Michael Sep 17 '13 at 20:22
  • Although I don't expect any compiler to ever do anything other than exactly what we both expect in this case, isn't it technically undefined behavior to perform arithmetic on a pointer which lead to a result which is outside the bounds of the array into which the starting pointer originated? So, e.g. `p` starts inside of `array[0]`, and then `p + 10` results in a pointer outside of `array[0]`. I thought that was UB? – Benjamin Lindley Sep 17 '13 at 20:50
  • @BenjaminLindley: Disagree there. While there is no direct quote in the standard that claims this to be valid, the behavior is guaranteed and is well defined. The standard mandates the layout of the two arrays, and that layout constraints imply that the last element of the first subarray is contiguous to the first element of the second subarray, which means that given a pointer to the first you can reach the second by incrementing the pointer by 1. – David Rodríguez - dribeas Sep 17 '13 at 21:05
0

By dereferencing one level at a time. For a 2D array and 3D array:

#include <cstdio>

int A[2][2];

int B[2][2][2];

int main() {
    // Set A[1][1] to 2
    *(*(A+1) + 1) = 2;
    printf("%d\n", A[1][1]);

    // Set B[1][1][1] to 3
    *(*(*(B+1) + 1) + 1) = 3;
    printf("%d", B[1][1][1]);
}

In general *(...*(*(array_of_N_dimensions + D1) + D2) ... + DN) will provide you access to array_of_N_dimensions[D1][D2]...[DN].

0

Here is some self teaching test code for you. Hope that helps.

#include < iostream >

int main()
{
    int a[2][2];

    a[0][0] = 1;
    a[0][1] = 2;
    a[1][0] = 3;
    a[1][1] = 4;


    for (int i=0; i < 4; ++i)
    {
        std::cout << *(*a+i) << std::endl;
    }

    return 0;
}
siphr
  • 421
  • 4
  • 12
0

The other answers, based on pointer arithmetic, are technically correct, but only if you are sure that your array is allocated like A[rows][cols]. This is very often not the case, and even if you implement your array like that you cannot be sure that another developer won't refactor it. The moment the other developer changes type A[rows][cols] to vector< vector< type > > A your code would break.

Therefore I would advise NOT to use pointer arithmetic across rows. If you are concerned about performance - don't: the compiler will automatically use pointer arithmetic to access array elements where applicable. More importantly, the compiler won't use pointer arithmetic where not applicable.

Michael
  • 5,775
  • 2
  • 34
  • 53
  • A vector is *not* an array, and a `vector>` has a completely different memory layout than an array of arrays. The common implementation of a multidimensional matrix is usually a single `vector<>` with `rows*cols` elements and pointer arithmetic inside the class that manages the object. I don't think I would use `vector>` as a substitute for an array of multiple dims ever (the only advantage of `vector>` is that it can be jagged, but that is not the case of arrays! – David Rodríguez - dribeas Sep 17 '13 at 20:29
  • Well, that was just an example of refactoring that would break pointer arithmetic code. Instead of vector< vector< type > > A it should have been non_continuous_container< type > A. :) – Michael Sep 17 '13 at 20:45
-2

2-dimensional arrays are stored row after row in memory, so you can access A[i][j] using index A+i*N+j where N is row length.

dkrikun
  • 1,228
  • 1
  • 15
  • 23