Fast way to copy an array - c

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!

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

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()...

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
}

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.

Related

Typedef to a double array of ints

I am trying to learn about an implementation of some code that uses a typedef to a double array and also uses pointers and I am having some difficulty understanding the code and details on how the code works and what types the variables are and what points to what.
I have tried playing around with different implementations and trying to understand how it works but the results I have gotten have been not what I have expected.
Heres some code I tried to test:
typedef int array[2][6];
array *arr;
arr = (array*)malloc(sizeof(array));
*arr[0][0]=2;
*arr[0][1]=4;
*arr[1][0]=3;
*arr[1][1]=5;
printf("line 1: %d %d\nline 2: %d %d\n",*arr[0][0],*arr[1][0],*arr[0][1],*arr[1][1]);
int *in = (int*) ((*arr)[0]);
printf("in = %d\n",in[1]); // results are unexpected
The code that I am actually looking at is for a ping pong buffer and is (simplified) as follows:
int buffer_count = 2; // 2 ping pong buffers
int sample_size = 15;
typedef int PingPong_t[buffer_count][sample_size];
PingPong_t *inputstream;
// logic goes here to determine pingpong_idx
int pingpong_idx = 0; // I believe this is to choose the first or second buffer
int *pcmIn = (int*)((*inputstream)[pingpong_idx]);
// do processing
I expect that pcmIn is an integer array of the current ping or pong buffer, but I am having trouble proving that to myself or I am just unsure what the datatypes actually are and what it is actually doing.
A good question I might have is, what is the type of inputstream? Is it correct to say that inputstream is a pointer to a double array of integers? Or is inputstream a double array of integer pointers?
Then what would be the type of pcmIn?
Let's break it down.
typedef int PingPong_t[buffer_count][sample_size];
This will make PingPong_t represent a 2D array of integers.
So, you can have
PingPong_t p = {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},{3,4,5,6,7,8,9,10,11,12,13,14,15,16,17}};
Then, we declare a pointer to this type as
PingPong_t *inputstream;
which means that inputstream is a pointer to whatever PingPong_t represents. It is not an array, not an array of pointers, just a pointer.
Since PingPong_t essentially means int x[2][15], inpustream will mean int (*y)[2][15].
Suppose we had something like
inputstream = &p;
Then, inputstream will point to the 2D array that is p. A custom pointer of type 2-dimensional (2 x 15) int array.
So, inputstream is int (*)[2][15] and p is int [2][15].
Now, playing it further, let us suppose we were to increment inputstream.
Incrementing a pointer will add the size of the type it points to.
So, in our case incrementing inpustream adds sizeof(int)*2*15 i.e. 120 (my machine has 4-byte int). Note that it does not add sizeof(int) here as its base type is not int but a 2D array of ints.
Finally, pcmIn is an int pointer (which can be thought of as a 1D array here), we are assigning like this
int *pcmIn = (int*)((*inputstream)[pingpong_idx]);
which fetches the first row (pingpong_idx) of the 2D array that inputstream points to, and assigns it to pcmIn.
Furthermore, you are getting unexpected results in your example above as you are assigning to the array in wrong manner. Since arr is a pointer to 2D array, you assign a value to an element like this
(*arr)[0][1]=4;
and not like this
*arr[0][1]=4;.
The latter will mean that arr is a 2D array of pointers and you are basically setting the value of [0][1]th pointer to 4, which is not what you had planned.
arr is not a 2D array and so arr[0][1] will mean the adding sizeof(int)*15 to the value of arr, and *arr[0][1] is basically getting/setting value at that address. In effect, the [0][1]th value is still uninitialized.
But, then how does *arr[0][0]=2; and printf("in = %d\n",in[0]); work?
Because, doing *arr[0][0]=2; will set the value of [0][0]th element to 2.

Add item to empty array in C and getting array length

I've taking many attempts at solving this problem but failed every time.
I have an array
char *array[1024] = {};
Now I would like to add an item to the array and would also access the items by numbers
For example:
array[0] would be the first item
array[1] would be the second
array[2] would be the third item
But also I would like to know how many items are in the array so I could use something like
for(int i = 0; i <= totalitemsinarray; i++) {
print(array[i]);
}
You cannot change the size of an array in C. You can however allocate a sufficiently large array and then fill it up with entries. First, declare an array with a sufficient size, say, 1024.
char *array[1024];
Then declare a variable fill that counts the number of used slots in array. Initialize it to 0 as 0 slots are used in the beginning. Then, each time you insert an item, increment fill:
array[fill++] = ...;
...
array[fill++] = ...;
Make sure that you never attempt to insert more than 1024 items into the array, C doesn't check that for you.
For a more flexible approach, use malloc() to allocate memory for the array and then periodically enlarge it with realloc() when it's full. If you increase the array size in exponential steps (say, multiply with Φ = 0.5 + 0.5 √2 &approx; 1.61), this runs in O(1) amortised time per entry inserted.
There is no way to do what you're asking directly with C. One option could be if you knew that only certain values were valid. For example, you have an array of char *s so often people use NULL as a flag/invalid value. In that case you could initialize your array to have all NULLs and use that to know the size of the array:
char *array[1024];
memset(array, 0, sizeof(array));
/* .... */
for (int i = 0; i < sizeof(array)/sizeof(char*); i++) {
if (array[i]) {
printf("%s\n", array[i]);
}
}
char *array[1024] = {};
First, that is an array with 1024 char pointers/strings. Those elements can be 0s or plain garbage. If you don't plan to set them all you may want to nullify the array.
For the matter of storing the values and the count you might want to have a look at structs. For example:
typedef struct elem {
int count;
char *value;
} elem;
Then elem.count would be the number and elem.value would be the value accordingly.
And then initialize them in a for loop.
The only really valid way to approach this, is to dynamically grow the array. Allocate the array on the heap, and manage two counts: 1. the count of currently used elements, and 2. the count of elements for which you currently have memory allocated. Something like this:
//the setup
size_t arrayLength = 0, allocatedSize = 8;
int* array = malloc(sizeof(*array) * allocatedSize);
//grow the array -> first check that we have space to add an element
if(arrayLength == allocatedSize) {
array = realloc(array, allocatedSize *= 2);
assert(array);
}
assert(arrayLength < allocatedSize);
//grow the array -> add an element
array[arrayLength++] = ...;
You see, the realloc() call is not too much hassle, but it will protect you from bugs when the requirements change. My experience is that any fixed limit in the code, as insanely large as it may seem to be, will eventually be exceeded, and miserable failure will result. The only safeguard is to use as much memory as needed everywhere.

Deep copying array in C... malloc?

I'm trying to make a deep copy of an array in C (originalBoard being the copy):
int gy, gx;
for (gy=0; gy<9; gy++)
{
for (gx=0; gx<9; gx++)
{
g.originalBoard[gy][gx]=g.board[gy][gx];
}
}
This does not seem to be working out, and I'm guessing this is just making pointers to the original board array.
So would the solution be to try and use malloc? Like:
int* g.originalBoard[9][9]=malloc(sizeof(g.board[9][9]));
btw this is a 9x9 two dimensional array. What would the syntax be (the compiler gives an error for the above line...)?
I think you need this:
//assuming g.originalBoard is array of array of integers and same for g.board
int *originalBoard = malloc(sizeof(g.board));
memcpy(originalBoard, g.board, sizeof(g.board));
This is the correct place to use memcpy. You probably want
g.originalBoard = (int *)malloc(9 * 9 * sizeof(int));
if (NULL == g.originalBoard) {
/* malloc failed, so handle the error somehow */
}
memcpy(g.originalBoard, g.board, 9 * 9 * sizeof(int));
You may notice that in the above solution you have to use g.board[r * 9 + c] to access the item at index (r, c), rather than two indices. This is because of the way this dynamically allocates memory - at compile-time g.board and g.originalBoard are just pointers, not arrays. Alternatively, if you have control over the definition of the type of g, you can hardcode the size of the matrix as
struct foo {
int board[9][9];
int originalBoard[9][9];
/* Other fields here */
};
Then you wouldn't have to malloc extra space for g.board and g.originalBoard - those two fields would be automatically allocated whenever you allocated space for g itself. Also, you could use g.board[r][c] instead of g.board[r * 9 + c].
By the way, if you are trying to execute the following 'intended' task on the arrays,
int* g.originalBoard[9][9]=malloc(sizeof(g.board[9][9]));
then you should change the above line to
int* g.originalBoard[8][8]=malloc(sizeof(g.board[8][8]));
because this is a 9x9 two dimensional array and in C arrays are ZERO-based.

Declaring an array in C without giving size

When declaring an array like this:
int array[][] = {
{1,2,3},
{4,5,6}};
I get an error saying: "Array type has incomplete element type"
What is going on??
With an N-dimensional array (N>0), you need to define the sizes of N-1 dimensions; only one dimension can be left for the compiler to determine, and it must be the first dimension.
You can write:
int d1[] = { ... };
int d2[][2] = { ... };
int d3[][2][3] = { ... };
Etc.
You need to specify all the dimensions except the highest. The reason is that the compiler is going to allocate one big block of memory, as opposed to one array of pointers pointing to their own little arrays. In other words,
int array[][3][4] = ...;
will allocate one contiguous region of memory of size 3*4*(however many 3x4 arrays you declare here). Thus when later on in your code, you write
array[1][2][3] = 69;
in order to find where in memory to write 69, it starts at address (array), then jumps forward 12*sizeof(int) to get to array[1], plus 2*4*sizeof(int) to get to array[1][2], plus 3*sizeof(int) to finally get to the start of array[1][2][3]. Compare this to writing, for example,
int ***array = new int**[n];
for(i=0; i<n; i++)
{
array[i] = new int * [3];
for(j=0; j<4; j++)
array[i][j] = new int[4];
}
(sorry if my syntax isn't exact...been awhile since I've had to code something like this in C). In this example, array points to a block of code n*sizeof(int**) bytes long. Each element of this array points to another array of size 3*sizeof(int*) bytes long. Each element of these arrays points to another array of size 4*sizeof(int) bytes long. In this case, instead of calculating that array[1][2][3] is at address (array + something), it would need to follow a few different pointers in memory before finding where to write 69.
You have to tell it at least all the dimensions except the largest.
ie in your case
int array[][3] = {
{1,2,3},
{4,5,6}};

Coding problem using a 2-d array of structs inside another struct in C

I am working with a 2-dimensional array of structs which is a part of another struct. It's not something I've done a lot with so I'm having a problem. This function ends up failing after getting to the "test" for-loop near the end. It prints out one line correctly before it seg faults.
The parts of my code which read data into a dummy 2-d array of structs works just fine, so it must be my assigning array to be part of another struct (the imageStruct).
Any help would be greatly appreciated!
/*the structure of each pixel*/
typedef struct
{
int R,G,B;
}pixelStruct;
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
imageStruct ReadImage(char * filename)
{
FILE *image=fopen(filename,"r");
imageStruct thisImage;
/*get header data from image*/
/*make a 2-d array of of pixels*/
pixelStruct imageArr[thisImage.height][thisImage.width];
/*Read in the image. */
/*I know this works because I after storing the image data in the
imageArr array, I printed each element from the array to the
screen.*/
/*so now I want to take the array called imageArr and put it in the
imageStruct called thisImage*/
thisImage.arr = malloc(sizeof(imageArr));
//allocate enough space in struct for the image array.
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*/
//test to see if assignment worked: (this is where it fails)
for (i = 0; i < thisImage.height; i++)
{
for (j = 0; j < thisImage.width; j++)
{
printf("\n%d: R: %d G: %d B: %d\n", i ,thisImage.arr[i][j].R,
thisImage.arr[i][j].G, thisImage.arr[i][j].B);
}
}
return thisImage;
}
(In case you are wondering why I am using a dummy array in the first place, well it's because when I started writing this code, I couldn't figure out how to do what I am trying to do now.)
EDIT: One person suggested that I didn't initialize my 2-d array correctly in the typedef for the imageStruct. Can anyone help me correct this if it is indeed the problem?
You seem to be able to create variable-length-arrays, so you're on a C99 system, or on a system that supports it. But not all compilers support those. If you want to use those, you don't need the arr pointer declaration in your struct. Assuming no variable-length-arrays, let's look at the relevant parts of your code:
/*data for each image*/
typedef struct
{
int height;
int width;
pixelStruct *arr; /*pointer to 2-d array of pixels*/
} imageStruct;
arr is a pointer to pixelStruct, and not to a 2-d array of pixels. Sure, you can use arr to access such an array, but the comment is misleading, and it hints at a misunderstanding. If you really wish to declare such a variable, you would do something like:
pixelStruct (*arr)[2][3];
and arr would be a pointer to an "array 2 of array 3 of pixelStruct", which means that arr points to a 2-d array. This isn't really what you want. To be fair, this isn't what you declare, so all is good. But your comment suggests a misunderstanding of pointers in C, and that is manifested later in your code.
At this point, you will do well to read a good introduction to arrays and pointers in C, and a really nice one is C For Smarties: Arrays and Pointers by Chris Torek. In particular, please make sure you understand the first diagram on the page and everything in the definition of the function f there.
Since you want to be able to index arr in a natural way using "column" and "row" indices, I suggest you declare arr as a pointer to pointer. So your structure becomes:
/* data for each image */
typedef struct
{
int height;
int width;
pixelStruct **arr; /* Image data of height*width dimensions */
} imageStruct;
Then in your ReadImage function, you allocate memory you need:
int i;
thisImage.arr = malloc(thisImage.height * sizeof *thisImage.arr);
for (i=0; i < thisImage.height; ++i)
thisImage.arr[i] = malloc(thisImage.width * sizeof *thisImage.arr[i]);
Note that for clarity, I haven't done any error-checking on malloc. In practice, you should check if malloc returned NULL and take appropriate measures.
Assuming all the memory allocation succeeded, you can now read your image in thisImage.arr (just like you were doing for imageArr in your original function).
Once you're done with thisImage.arr, make sure to free it:
for (i=0; i < thisImage.height; ++i)
free(thisImage.arr[i]);
free(thisImage.arr);
In practice, you will want to wrap the allocation and deallocation parts above in their respective functions that allocate and free the arr object, and take care of error-checking.
I don't think sizeof imageArr works as you expect it to when you're using runtime-sized arrays. Which, btw, are a sort of "niche" C99 feature. You should add some printouts of crucial values, such as that sizeof to see if it does what you think.
Clearer would be to use explicit allocation of the array:
thisImage.arr = malloc(thisImage.width * thisImage.height * sizeof *thisImage.arr);
I also think that it's hard (if even possible) to implement a "true" 2D array like this. I would recommend just doing the address computation yourself, i.e. accessing a pixel like this:
unsigned int x = 3, y = 1; // Assume image is larger.
print("pixel at (%d,%d) is r=%d g=%d b=%d\n", x, y, thisImage.arr[y * thisImage.width + x]);
I don't see how the required dimension information can be associated with an array at run-time; I don't think that's possible.
height and width are undefined; you might want to initialise them first, as in
thisImage.height = 10; thisImage.width = 20;
also,
what is colorRGB?
*thisImage.arr = *imageArr; /*put imageArr into the thisImage imagestruct*
This won't work. You have to declare arr as colorRGB **, allocate it accordingly, etc.
it looks like you are trying to copy array by assignment.
You cannot use simple assignment operator to do that, you have to use some function to copy things, for example memcpy.
*thisImage.arr = *imageArr;
thisimage.arr[0] = imagearr[0];
The above statements are doing the same thing.
However this is not most likely what causes the memory corruption
since you are working with two dimensional arrays, do make sure you initialize them correctly.
Looking at the code, should not even compile: the array is declared as one-dimensional in your image structure but you refer to as two-dimensional?

Resources