How to copy dynamically allocated array of struct? - c

I have been struggling with this. What I have found here on stackoverflow, and other places was to just do:
memcpy(&a, &b, sizeof(b));
But for me, that did not work. So I thought, I share what worked for me without any unexpected behavior.

Assume you have:
#define N 42
struct struct_name *a = malloc(sizeof *a * N); // allocate N objects
struct struct_name *b = malloc(sizeof *b * N); // allocate N objects
then the correct memcpy call to copy the array of structure objects is:
memcpy(a, b, sizeof *a * N);

In my case previous solutions did not work properly, e.g. the one in the question! (it copied about half of only the first element).
So in case, somebody needs a solution, that will give you correct results, here it is:
memcpy(a, b, n * sizeof(*b));
More detail:
int i, n = 50;
struct YourStruct *a, *b;
a = calloc(n, sizeof(*a));
b = malloc(n * sizeof(*b));
for (i = 0; i < n; ++i) {
// filling a
}
memcpy(b, a, n * sizeof(*a)); // <----- memcpy 'n' elements from 'a' to 'b'
if (a != NULL) free(a); // free 'a'
a = calloc(2*n, sizeof(*a)); // 'a' is size 2n now
memcpy(a, b, n * sizeof(*b)); // <------ memcpy back the 'n' elements from 'b' to 'a'
// do other stuff with 'a' (filling too)...
Some notes:
I used calloc for a, because in the '// filling a' part I was doing
operations that required initialized data.
I could have used realloc as well.
I was kind of doing a dynamically growing array (with doubling size -> log(n)), but here I simplified it.
You should check, if memory allocation is successful or not (a,b NULL or not). But here, I removed those checks for simplification.

Related

Generic quicksort not working

I'm trying to make a generic quicksort function, and I fail to understand what's wrong with what I'm doing, because it's not working properly.
Here is my code:
typedef bool (*CmpFunction)(void*, void*);
void swap(void *c1, void *c2)
{
assert(c1 && c2);
int c = *(int*)c1;
*(int*)c1 = *(int*)c2;
*(int*)c2 = c;
}
void quick_sort(void* a, int n, CmpFunction swap)
{
int p, b = 1, t = n - 1;
if (n < 2)
return;
swap((char*)a, (char*)a+n/2);
p = *(int*)a;
while(b <= t) {
while(t >= b && (char*)a + t >= p )
t--;
while(b <= t && (char*)a + b < p)
b++;
if ( b < t)
swap((char*)a+(b++), (char*)a+(t--));
}
swap((char*)a, (char*)a+t);
quick_sort(a, t, swap);
n=n-t-1;
quick_sort(a + t + 1, n, swap);
}
While the original quicksort function, without me trying to make it generic is:
void quick_sort(int a[], int n)
{
int p, b = 1, t = n - 1;
if (n < 2)
return;
swap(&a[0], &a[n/2]);
p = a[0];
while(b <= t) {
while(t >= b && a[t] >= p )
t--;
while(b <= t && a[b] < p)
b++;
if ( b < t)
swap(&a[b++], &a[t--]);
}
swap(&a[0], &a[t]);
quick_sort(a, t);
n=n-t-1;
quick_sort(a + t + 1, n);
}
void swap(int *c1, int *c2)
{
int c = *c1;
*c1 = *c2;
*c2 = c;
}
I'm using this main():
int main(){
char b[] = {'a','t','b','c','y','s'};
int c[] = {1,4,6,3,5,7};
quick_sort(c, 6, &swap);
for (int i=0;i<6;i++)
printf("%d | ", c[i]);
return 0;
}
Now we all agree that the output should be:
1, 3, 4, 5, 6, 7
which is indeed what I get when running the NOT generic function.
When I run my generic(upper) function I get basically trash.
You all have any ideas where I'm wrong? :)
The most obvious issue: Your input data is an int array, typecasted into a void * pointer, then forced into a char * pointer:
swap((char*)a, (char*)a+n/2);
Here you force that into a char * pointer, and jumping n/2 into it.
char * is an array of 1 byte size elements
int * is an array of 2, 4 or 8 byte size elements depending on compiler/OS/CPU.
So char *a +1, void give you the second byte of the first element of the initial array.
qsort is a generic sorting function. You give it an array, the size of the elements in the array, the number of elements, and a comparison function.
typedef int(*compare)(const void*, const void*);
void quicksort(void *base, size_t num_elements, size_t width, compare *cmp);
To move through the array the sorting function needs to know the width of each element so it can do the pointer arithmetic correctly. An array of char will be 1 byte per element. An array of int is probably 4 bytes. double will be 8. base[4] of a char array is base + 4*1, but it's base + 4*4 for an int array. Ultimately base[n] is base + (n * width).
To avoid making assumptions about the data in the elements, or how you want them sorted, the compare is used to compare elements for sorting. It returns < 0 if a < b, 0 if a == b and > 0 if a > b. This allows it to be as simple as return a - b for most numbers.
An example function for comparing integers:
int cmp_int(const void* _a, const void* _b) {
/* Do the casting separately for clarity */
int *a = (int *)_a;
int *b = (int *)_b;
return *a - *b;
}
There's no need to pass in a swap function. So long as you know the size of the elements a single swap function will serve. The one from #HonzaRemeš' answer works.
void swap(void * a, void * b, size_t size) {
/* Temp buffer large enough to contain an element */
char tmp[size];
memcpy(tmp, a, size);
memcpy(a, b, size);
memcpy(b, tmp, size);
}
With all this in mind, your function is not being given the element size (ie. width) so it cannot correctly move through the array. It's also unnecessarily passing in a swap function, but there's no need for this if you know the size of the elements. And you're lacking a proper comparison function to compare elements. Not much of a generic sort function if it can't compare things to sort them.
You are trying to do something the C language is not very appropriate for. If you want to do it, you need some background knowledge about pointer arithmetics.
Specifically, for a T *, where T is a type with size N (sizeof(T) == N),
T * ptr;
ptr = (T *) 0x0100;
ptr = ptr + 1;
// ptr now has value 0x100 + N
That means you can't have a generic function which will operate on data arrays without knowing the size of the array element.
So I suggest you rewrite your quick_sort and swap functions to incorporate size parameters. You then cast your pointers to char * and use the size parameter to make the functions work correctly. Example swap function follows.
void swap(void * c1, void * c2, size_t size) {
char tmp[size]; // temporary buffer big enough to contain c1 data
memcpy(tmp, c1, size);
memcpy(c1, c2, size);
memcpy(c2, tmp, size);
}
Modifying quick_sort is left as an exercise :). Remember though that when you don't know the size of your data, you must use memcpy(dst, src, size) instead of dst = src, you must use memcmp(a1, a2, size) >= 0 instead of a1 >= a2 and that your pointer access must be multiplied by size (exerpt from quick_sort follows):
EDIT: #Schwern points out in the comments why using memcmp() may not work. Comparing values of unknown size and format (endianness, float X int) would probably require a generic comparison function (which would likely be next to impossible to write). That takes us back to C's ill-suitedness for this task.
void quick_sort(void *a, int n, size_t size) {
char[size] p;
int b = 1, t = n - 1;
if(n < 2)
return;
// Using new swap with 'size' parameter
swap(&a[0], &((char *)a)[n / 2 * size], size);
// or swap((char *)a + 0, (char*)a + (n / 2 * size), size);
memcpy(p, a, size);
while(b <= t) {
while(t >= b && memcmp((char *)a[t * size], p, size) >= 0) {
...
}
You can then write wrapper macros to pass the size parameter to the quick_sort function.
#define QSORT(arr, n) quick_sort((arr), (n), sizeof((arr)[0]))

Generic bidimensional array

I want to create a bidimensional array like so:
void **mdeclaraMatrice(int nrLini,int nrColoane, int sizeOfElement)
{
int i;
void **m = malloc(nrLini * 4);
if(m==NULL)
return NULL;
for(i=0; i<nrLini; i++)
{
*(m + (i*4)) = malloc(nrColoane * sizeOfElement);
if(*(m + (i*4)) == NULL)
return NULL;
}
return m;
}
I whant to use it like this:
int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));
but it doesn't work. What do I do wrong?
You should use m[i] instead of *(m+i*4) and let the compiler do the arithmetic.
In addition, you should deallocate the already-allocated memory in case of a failure.
Try this instead:
void **mdeclaraMatrice(int nrLini, int nrColoane, int sizeOfElement)
{
int i;
void **m = malloc(nrLini * sizeof(void*));
if (m == NULL)
return NULL;
for (i=0; i<nrLini; i++)
{
m[i] = malloc(nrColoane * sizeOfElement);
if (m[i] == NULL)
{
while (i-- > 0)
free(m[i]);
free(m);
return NULL;
}
}
return m;
}
[not an answer to the question, but to the indented usage of the proper answer as given by others]
To access the void pointer array as an array of int, doing this
int **m = (int **)mdeclaraMatrice(n,m,sizeof(int));
is not correct, as per the C-Standard only void* converts to any other pointer properly, void** doesn't necessarily. So it shall correctly be
void ** ppv = mdeclaraMatrice(n,m,sizeof(int));
int * pi = *ppv; /* Please note, there is NO casting necessary here! */
Then access the members like so:
pi[0] = 42
pi[1] = 43;
...
Which essently is the same as doing
*((int *) (pi + 0)) = 42;
*((int *) (pi + 1)) = 43;
which indeed does not make sense really as pi already is int*, so the fully correct approach (also taking into account the 2nd dimension) would be:
((int *)(ppv[0]))[0] = 42;
((int *)(ppv[0]))[1] = 43;
Which could be made usable by definging a macro:
#define GENERIC_ARRAY_ELEMENT(type, address, r, c) \
((type *)(address[r]))[c]
GENERIC_ARRAY_ELEMENT(int, ppv, 0, 0) = 42;
GENERIC_ARRAY_ELEMENT(int, ppv, 0, 1) = 43;
I will address the problem of allocation an array of void pointers and then interpreting them as an array of int pointers.
int **nope = (int **)mdeclaraMatrice(n,m,sizeof(int));
Even assuming the allocation was completely correct the assignment and later usage of nope is undefined behavior. void** and int** have incompatible types.
What you can do is the following. Assign the void pointers one by one to an array of int pointers.
void** arrp = mdeclaraMatrice(n,m,sizeof(int));
int* arr[n] ;
for( size_t i = 0 , i < n ; i++ )
arr[i] = arrp[i] ;
And then use the arr array, When you want to free the memory you free the original pointer:
free( arrp ) ;
The problem occurs in this line:
*(m + (i*4)) = malloc(nrColoane * sizeOfElement);
You have to know that when adding a number to an address, the address will be incremented by the number times the size of the object the address points to. So if your pointer points to an object that is of size 4 bytes, and you add 1 to it, then the address will automatically be incremented by 4, not by 1. So you should abandon *4.
Also, use the sizeof operator when allocating space, because addresses (and thus pointers) can have different sizes on different processor architectures.
Actually, you don't even need your generic 2D array function if you know the powerfull VLA features of C99. To allocate a true 2D array (no index array required), you just do this:
int (*twoDIntArray)[width] = malloc(height*sizeof(*twoDIntArray));
That's it. Accesses are just as simple:
twoDIntArray[line][column] = 42;
In this code, twoDIntArray is a pointer to an array of width integers. The malloc() call simply allocates enough space for height such line arrays. When you do the pointer arithmetic twoDIntArray[line], you add the size of line line arrays to the pointer, which produces the address of the corresponding line array. This line array is then indexed by the second array subscript [column].
Needless to say that freeing such an array is just as trivial:
free(twoDIntArray);

C - What happens to an array of pointers when the array is freed?

I am currently programming in C, and I am creating an array of pointers. These pointers contained in the array will last for the duration of the entire program.
Let's say the array of pointers is array A. I then create another array of pointers B, and I put an element of array A into array B. Then, I free array A.
What will happen to the element in array B? Will it no longer be valid since array A has been freed, or will it still be valid, since the actual pointer is still valid in memory?
Thanks
Here's an example of what my code will look like--
int a = 1;
int b = 2;
int c = 3;
int **array_a = (int **) malloc (sizeof (int *) * 3);
array_a[0] = &a;
array_a[1] = &b;
array_a[2] = &c;
int **array_b = (int **) malloc (sizeof (int *) * 1);
array_b[0] = array_a[0];
free(array_a);
Now, what happens to array_b[0]?
If you do this
int *a = malloc(10 * sizeof(int));
for (int i = 0 ; i != 10 ; i++) {
a[i] = 2*i+1;
}
int *b = a;
free(a);
then b would be invalid as well.
If you do this, however
int *a = malloc(10 * sizeof(int));
for (int i = 0 ; i != 10 ; i++) {
a[i] = 2*i+1;
}
int *b = malloc(10 * sizeof(int));
memcpy(b, a, 10 * sizeof(int));
free(a);
then b remains valid.
The pointers itself doesn't change, it still points where it pointed. The only thing is that the location it points to might be allocated to some other program. You could still write and read the location with undefined behaviour. Check this code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a = (int *)malloc(3 * sizeof(int));
a[0] = 1, a[1] = 2, a[2] = 3;
free(a);
// a = NULL // if you add this, the following will crash.
printf("%d\n", a[0]);
printf("%d\n", a[1]);
printf("%d\n", a[2]);
return 0;
}
If you are lucky, you could still get the correct result. But it's just luck.
So it's usually good idea to set the pointer to NULL after being freed.
So I just learned a little bit about free() not too long ago, so I'm sorry to say I don't know too much about it yet, but here's the little that I do know:
To return dynamically allocated memory to the system, you use the free() function. My professor used this kind of example:
struct listNode *Bob;
Bob = &any instance of listNode;
free(Bob);
So I believe B will still remain valid while A is no longer referenced. Java periodically collects dynamically allocated memory that is no longer referenced and it goes in the 'garbage.' C doesn't do that, which is why we use free(). Hope that helps a bit. I'm still learning myself. Good question :)
C interprets an array as the address of the base element, so depending on how you have freed the array you may not have freed the element at all.
However, assuming you did free all the elements of the array, your pointer in array B will still be there (it will still point to the same location in memory). However, you really don't know what is at that location because you already freed the memory there. You may still get the original data stored there, or it may have been overwritten. Definitely not safe to use it, though.
These three lines declare memory for three integers, and initialize the integers. Should you do this outside of a function, you can happily take the address of these variables and store them in your array.
int a = 1;
int b = 2;
int c = 3;
However, should the above three variables be declared in a function (on the stack) and you take the address of them, and store those addresses somewhere, you have created a (potential) dangling pointer problem.
This line allocates enough memory to hold three pointers to int (12 or 24 bytes),
int **array_a = (int **) malloc (sizeof (int *) * 3);
Now you store the address of the earlier defined variables a,b,c into the array_a[],
array_a[0] = &a;
array_a[1] = &b;
array_a[2] = &c;
Which is either perfectly harmless, or very dangerous, depending upon where a,b,c were declared, for example,
int** youfun()
{
int a = 1;
int b = 2;
int c = 3;
int **array_a = (int **) malloc (sizeof (int *) * 3);
array_a[0] = &a;
array_a[1] = &b;
array_a[2] = &c;
return(array_a); //very bad!
}
int a = 1;
int b = 2;
int c = 3;
int** mefun()
{
int **array_a = (int **) malloc (sizeof (int *) * 3);
array_a[0] = &a;
array_a[1] = &b;
array_a[2] = &c;
return(array_a); //safe, but strange
}
Declaring and allocating space for array_b[], and reserving a single memory location is similar to declaring and array of one pointer to int,
int **array_b = (int **) malloc (sizeof (int *) * 1);
The following assignment places the contents of array_a[0] (which is the address of variable a, &a, from above), and is only as dangerous/innocuous as having the &a stored in array_a[0],
array_b[0] = array_a[0];
Freeing the array_a is harmless, because nothing is stored in array_a which might 'leak', and does not affect array_b[0], as that contains the address of a, &a,
free(array_a);
Suppose you did the following instead,
int **array_a = (int **) malloc (sizeof (int *) * 100);
int ndx;
for(ndx=0; ndx<100; ++ndx)
array_a[ndx] = malloc( sizeof(int) );
You would now have allocated 100+1 memory locations, which is still fine.
Then suppose you allocated array_b will enough space to hold all of array_a[],
int **array_b = (int **) malloc (sizeof (int *) * 100);
int ndx;
for(ndx=0; ndx<100; ++ndx)
array_b[ndx] = malloc( sizeof(int) );
This would leak memory (pointed at by array_b), plus the memory pointed at by each array_b[ndx], for a total of 100+1 memory location leaks,
array_b = array_a; //discarded memory references at array_b[0..99], and array_b
Now suppose you did both of these,
array_b = array_a; //you just discarded the memory references at array_b[0..99] and array_b
free(array_a); //you just discarded array_a[0..99]
The above would leak all memory pointed to by array_b, array_b[0..99] and all memory at array_a[0..99], as you only copied array_a's address, not the addresses at array_a[0..99].
Here is how you would copy the memory allocated at array_a[0..99],
for(ndx=0; ndx<100; ++ndx)
array_b[ndx] = array_a[ndx];

What does this C function do?

double *f(int n, double v)
{
double *a, *p;
a = malloc(n * sizeof(double));
if (a != NULL)
for (p = a; p < a + n; p++)
*p = v;
return a;
}
Can you explain me what this function is needed for? Does it copy the content of v in n? If yes, why does it return a? I really don't get it... Thanks in advance.
It returns a newly allocated double array of size n filled with value v, or NULL if the allocation fails.
This loop:
for (p = a; p < a + n; p++)
*p = v;
uses pointer arithmetic. As p is a pointer to a double, incrementing it will point to the next double to write. *p = v writes the double at the specified location.
double *f(int n, double v)
{
double *a, *p;
a = malloc(n * sizeof(double)); // allocate memory enough for "n" doubles (an array)
if (a != NULL) // if the allocation was successful
for (p = a; p < a + n; p++) // loop from the beginning of the array to the end
*p = v; // fill every element of the array with the value "v"
return a; // return the new array
}
So if I called this function:
double * myarray;
myarray = f(3, 1.3);
Now I have:
myarray[0] = 1.3
myarray[1] = 1.3
myarray[2] = 1.3
So to answers your questions:
Can you explain me what this function is needed for?
allocates and initializes an array of doubles.
Does it copy the content of v in n?
No. Considering v is a double and n is an int, that doesn't even make sense. It makes an array n large and initializes it with the value v.
If yes, why does it return a?
It returns a so you have a reference to the newly created array. (see example above on how it could be used)
It allocates an array of n doubles, initialising each element of the array to the value of v.
The function returns a to allow the caller to use this newly allocated array.
It allocs a memory area of n * sizeof(double) bytes and enterely fill it with v value
Allocate an array of n doubles in heap, fill it with v and return the pointer to it?
Duplicate the v n times into an array of float
The array is allocated in the function and contains n float elements.
at the end of the function each element in the array a is containing v as value

memcpy() with different data types

Trying to copy A into B....
char *A;
double *B;
unsigned int size = 1024;
A = malloc (size*size * sizeof (char));
B = malloc (size*size * sizeof (double));
//fill A here
memcpy (B, &A[0], (size*size * sizeof (char)));
Printing values in B don't match whats in A.
What's going wrong?
Thanks for any help!
Edit: The point of this is to test the memcpy function's speed in relation to the size of the L2 cache. I'm just wanting to make sure the code above is actually copying all of A into B. Sorry about leaving out this info: I just try to make it as simple as possible (and went too far this time)
It's hard to tell exactly what you are trying to do.
How are you printing values? Print routines like printf also depend on the type.
It sounds like you just want to get float input values. This can be done using the scanf family.
int num_floats = 10;
double* B = malloc (num_floats * sizeof (double));
int count;
for (count = 0; count < num_floats; count++)
{
printf("Insert float %d: ", count);
scanf("%f", &B[num_floats]);
}
for (count = 0; count < num_floats; count++)
{
printf("Float %d: %f", B[num_floats]);
}
free(B);
If you are trying to convert C-strings from char * to floating point numbers and don't want to use sscanf, you can also use atof.
const char* num_str = "1.01";
double num = atof(num_str);

Resources