Reputation: 41
So at the end of each iteration that I'm doing, I want to make my array be equal to my new array (which I have called array_new). I want every element of array to take the same value as is in array_new but I'm interested in getting my code as quick as possible and so copying everything across element-by-element as this current code does isn't an option:
for(i=0;i<N_a;i++) {
for(j=0;j<N_b;j++) {
array[i][j] = array_new[i][j];
}
}
This takes quite a long time because my values of N_a and N_b are very large. Is there a way to simply change what each of them point to so that I can start my next iteration more quickly? I've tried doing stuff like
double *temp = *array;
*array = *array_new;
*array_new = temp;
in order to try and avoid a slow element-by-element copying procedure but it doesn't seem to work for me. Effectively what I'm trying to make happen is for every element of array point to the corresponding element in array_new but I can't work out how to make the pointers do that.
Any help would be much appreciated!
Upvotes: 3
Views: 11589
Reputation: 40810
Two answer this, you first need to understand how the array is represented in memory. E.g. see this question: How are multi-dimensional arrays formatted in memory?
So first we need to know if you have a static array or not. If it is a static array then the task is particularly simple, because the data is laid out contiguously in memory. This means that if you have a 2x2 static array, with the content {{9, 8}, {7, 6}}
your memory could look like this:
Address 0 1 2 3 4 5 6 7 8
Content ? ? 9 8 7 6 ? ? ?
In this case your variable which is declared like this:
int[2][2] myArray;
is actually a pointer to address "2" and you can easily copy the whole thing. with memcpy:
int [2][2] newArray;
memcpy(&newArray, &myArray, sizeof(int)*2*2);
Notice that this copies starting from wherever "myArray" points (in my example that is 2) as many bytes as 2*2*sizeof(int). So 4 times the size of int. (For simplicity my example assume a size of one byte for an int, but of course on most systems it is 4 byte).
If you have a dynamic array, then it is a different story. In this case your memory for your array declared like this:
int** myArray;
may well look like this:
Address 0 1 2 3 4 5 6 7 8
Content 9 8 0 6 ? ? 7 6 ?
Note that the pointer myArray
still points to the Address "2". However at the address "2" you don't find the first value, but instead another pointer which points to "0". And here you find the values of the first "row" which are 9 and 8.
Next to the address "2" in number "3" you find the pointer to your second "row" which starts at position 6. As you can see, you can still find all your data, but you cannot copy them in a single go. To copy the whole array you will at least need the outer row:
int SIZE_X = 2;
int SIZE_Y = 2;
int** newArray = malloc(sizeof(int*)*SIZE_X);
for(i = 0; i < SIZE_X; ++i) {
newArray[i] = malloc(sizeof(int)*SIZE_Y);
memcpy(newArray[i], myArray, SIZE_Y*sizeof(int));
}
This should be faster then using two loops, as memcpy can use more efficient ways to copy than a copy loop.
Upvotes: 0
Reputation: 4220
If you just want to swap the pointers, not physically copying the data, and to still be able to access the arrays using indexes, here is an example of how it can be done:
#define N_a 2
#define N_b 3
typedef struct arr
{
int val[N_a][N_b];
} arr;
arr array = {{{11,12,13},{14,15,16}}};
arr array_new = {{{21,22,23},{24,25,26}}};
int main()
{
arr *p_array;
arr *p_array_new;
p_array = &array;
p_array_new = &array_new;
printf("%d %d\n", p_array->val[1][2], p_array_new->val[1][2]);
// output: 16 26
p_array = &array_new;
p_array_new = &array;
printf("%d %d\n", p_array->val[1][2], p_array_new->val[1][2]);
// output: 26 16
}
Upvotes: 0
Reputation: 40625
Your pointer-swap code is just a little bit off: you are dereferencing your pointers where you shouldn't. After all, the point of that code is to avoid copying data by just swapping two pointers. Here are the correct versions (depending on whether you use a true 2D array or an array of pointers to arrays):
//array is declared as
double (*array)[N_b];
double (*temp)[N_b] = array;
array = array_new;
array_new = temp;
or
//array is declared as
double** array;
double** temp = array;
array = array_new;
array_new = temp;
This is all you need, and it's definitely the fastest possible way to exchange contents of two buffers. Much faster than memcpy()
...
Upvotes: 1
Reputation: 3351
Since the memory size of your array is fixed, you can simply copy the memory block from one pointer to the other. It doesn't get any faster than that.
In c/c++
you could use memcpy
if that is the language you are using. Every language has something equivalent.
Edit: since you confirmed use of c
I can get more detailed:
memcpy(array_new,array,sizeof(VARIABLE_TYPE_of_ARRAY_ELEMENT)*N_a*N_b);
Upvotes: 8