I have a huge code using a 3D array managed with pointers. Something like:
int *** tab;
tab = malloc(m*sizeof(int**));
for(i= 1..n) tab[i] = malloc(n*sizeof(int*));
... etc...
and later the elements are accessed with:
tab[i][j][k] = ...
But because of specific issues with this structure, I would like to declare tab as a contiguous array instead but still use the syntax with 3 brackets in the code. The compiler will internally replace them like this:
tab[i][j][k] = ... => tab[i*m*n+j*m+k] = ...
So the array is accessed with only one pointer dereference. I'd like not to change the source code (no sed).
For example I could do this by declaring tab in stack:
int tab[n][m][l];
but unfortunately this doesn't work if m
and n
are runtime variables.
You can create a multidimensional array by creating a 2-D matrix first, and then extending it. For example, first define a 3-by-3 matrix as the first page in a 3-D array. Now add a second page. To do this, assign another 3-by-3 matrix to the index value 2 in the third dimension.
JavaScript arrays are a special type of object. To access an array item, the [] operator is used, for example colors[2] . The [] operator converts the expression inside the square brackets to a string.
You can use the ArraySet function to populate a 1D array, or one dimension of a multidimensional array, with some initial value, such as an empty string or zero. This can be useful to create an array of a certain size, without adding data to it right away.
Unless you are talking about static arrays, 1D is faster. Clearly the 2D case loses the cache locality and uses more memory. It also introduces an extra indirection (and thus an extra pointer to follow) but the first array has the overhead of calculating the indices so these even out more or less. Save this answer.
A C++ way is to enclose the 3D array in a class to have a natural accessor:
struct Arr3D
{
int *arr;
const int n, m, p; //size of the tab in 3 dimensions
public:
Arr3D(int n, int m, int l): n(n), m(m), p(l) {
arr = new int[n * m * p];
}
~Arr3D() {
delete[] arr;
}
int& val(int i, int j, int k) { // read-write accessor
// optionaly test for 0<=i<n...
return arr[k + p * (j + i * m)];
}
};
You create and use an array simply with:
Arr3D * parr = new Arr3D(3,4,5); // dynamic allocation
Arr3D arr(3, 4, 5); // automatic allocation
...
arr(1,2,3) = 5;
int i = arr(2,0,1);
Alternatively, if you want to keep the syntax tab[i][j][k]
you can if you use an auxilliary Arr2D class able to provide a view on a 2D array:
struct Arr2D
{
int *arr;
const int n, m; //size of the tab in 2 dimensions
const bool is_view;
public:
Arr2D(int n, int m): n(n), m(m), is_view(false) {
arr = new int[n * m];
}
Arr2D(int *arr, int n, int m): arr(arr), n(n), m(m), is_view(true) {}
~Arr2D() {
if (! is_view) delete[] arr;
}
int * operator[] (int i) {
return arr + i * m;
}
};
struct Arr3D
{
int *arr;
const int n, m, p; //size of the tab in 3 dimensions
public:
Arr3D(int n, int m, int l): n(n), m(m), p(l) {
arr = new int[n * m * p];
}
~Arr3D() {
delete[] arr;
}
Arr2D operator[](int i) {
return Arr2D(arr + i * p * m, m, p);
}
};
You can now simply use arr[i][j][k]
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With