Search code examples
cmultidimensional-arraymemmove

Shift elements by one index with memmove


I am trying to shift the elements in a dynamically created 3d array by one index, so that each element [i][j][k] should be on [i+1][j][k].

This is how my array creation looks like

typedef struct stencil{
int ***arr;
int l;
int m;
int n;}matrix;

void createMatrix(matrix *vector){

vector->arr = (int***) malloc(sizeof(int**) * (vector->l+2));
for (int i = 0; i< vector->l+2; ++i) {
    vector->arr[i] = (int**) malloc(sizeof(int*) * (vector->m+2));
    for (int j = 0; j < vector->m+2; ++j) {
        vector->arr[i][j] = (int*) calloc((vector->n+2),sizeof(int));
    }

}
}

This is basically what I want to achieve with memmove

for(int i = vector->l-1; i >= 0; --i){
    for(int j = vector->m; j >= 0; --j){
        for(int k = vector->n; k >= 0; --k){
            vector->arr[i+1][j][k] = vector->arr[i][j][k];
        }
    }
}

for some reason memmove shifts 2 indices.

memmove(&(vector->arr[1][1][1]), &(vector->arr[0][1][1]), (vector->l+2)*(vector->m+2)*(vector->n)*sizeof(int*));

Could anyone give me a hint?


Solution

  • When you create a dynamic multi-dimensional array like this, the array contents are not contiguous -- each row is a separate allocation. So you can't move it all with a single memmov().

    But you don't need to copy all the data, just shift the pointers in the top-level array.

    int **temp = arr[l-1]; // save last pointer, which will be overwritten
    memmov(&arr[1], &arr[0], sizeof(*arr[1]));
    arr[0] = temp;
    

    I've shifted the last element around to the first, to avoid having two elements that point to the same data. You could also free the old last element (including freeing the arrays it points to) and create a new first element, but this was simpler.