qsort dynamically created array in c - c

Hey guys (be forewarned that this question makes me feel n00b so I probably am),
I'm able to dynamically create an array and I'm able to use qsort effectively for a statically created array but am having trouble using qsort on a dynamically created one. I think I'm stumbling on my use of pointers.
struct my_struct {
FILE *fp;
int i;
};
So the array contains the above struct and I'd like to sort it by the int value.
Statically, I can do something like this:
struct my_struct array[4];
And sort:
qsort((void *) &array, sizeof(array) / sizeof(struct my_struct), sizeof(struct my_struct), *compare);
--
If I create the array thus:
struct my_struct* = malloc(sizeof(struct process) * 4);
Everything compiles and runs, however execution never goes into the compare function.
Any help would be greatly appreciated

sizeof(array) is (sizeof(struct my_struct) * array_size) for constant-size array, but it's only pointer size for dynamic one. You have to calculate actual size (one you passed to malloc) yourself and put it into qsort call.

Your invocation of qsort only works by accident:
qsort((void *) &array, sizeof(array) / sizeof(struct my_struct), sizeof(struct my_struct), *compare);
The address of an array has the same value but a different type from the address of the zeroth element of the array. The cast to void * is also superfluous; and the dereference of the comparator function is also aconventional. Normally, that'd be written:
qsort(array, sizeof(array) / sizeof(array[0]), sizeof(struct my_struct), compare);
Or:
qsort(array, sizeof(array) / sizeof(array[0]), sizeof(array[0]), compare);
If you have a dynamically allocated structure:
size_t num_items = 4;
struct my_struct *dynarr = malloc(sizeof(struct my_struct) * num_items);
or:
struct my_struct *dynarr = malloc(sizeof(*dynarr) * num_items);
then you will be specifying the number of elements differently in the call to qsort, but the rest is essentially unchanged:
qsort(dynarr, num_items, sizeof(*dynarr), compare);
Note in particular that there is no & in front of dynarr, which is a simple pointer variable, for all it has a possibly misleading name.
Why your code went wrong
A guess, but a plausible guess. If you wrote:
qsort(&dynarr, sizeof(dynarr) / sizeof(dynarr[0]), sizeof(dynarr[0]), compare);
then sizeof(dynarr) is the size of a pointer (say 8 bytes in a 64-bit program), and sizeof(dynarr[0]) is 16 bytes, so the size (number of elements) that you tell qsort() to sort is 0 (because 8 / 16 == 0), so the comparator would never be called. If your program is compiled as a 32-bit program, the sizes are 4 bytes for the pointer and 8 for the structure, so the result is still 0.
Note that if instead you passed 4 or num_items as the size of the array, then you'd get a crash. The address of dynarr is the wrong address to pass to the function; you want to pass the address value that is held in dynarr, not the address at which dynarr itself is stored.
NB: You should show the qsort() that doesn't work so we don't have to guess what you've written.

Related

Dynamically expanding array of structs C [duplicate]

This question already has answers here:
Dynamic array in C — Is my understanding of malloc and realloc correct?
(3 answers)
Closed 5 years ago.
So for my school project, a large CSV file will be entered through stdin and we will have to sort it based on column and print it out as a sorted csv file.
The step I am on right now is figuring out how to keep reallocing a struct of arrays so that it will grow if there is not big enough to hold the data coming in from stdin. We don't know the exact amount of rows that will be inputted in the CSV file. Right now we just used a static amount to test and see if the values are assigned to the structs.
I am still a beginner at C so I do not clearly know how I would iterate through a pointer like I would iterate through an array. Since we are using a static amount of structs in the array, we can just iterate using array[i] like in Java but how would you iterate through something like *array?
I do not know where to start for creating this dynamic array. I tried
struct array* testArray = (array*)malloc(sizeof(testArray));
but I have no idea how to iterate through it like I did with the static array by using array[i].
Any help would be greatly appreciated, sorry for the wall of text...
You can navigate through a malloced space the same way as with an array (using indicies), but it seems that your main issue lies in your use of malloc. Malloc's argument is the size in number of bytes that you want to allocate. So if you want to have an array of structs, you would first need to find out how many bytes one struct contains using sizeof(struct array), and then determine how large of an array you want, let's say N. So that line of code should look more like struct array* testArray = malloc(N * sizeof(struct array));. The return value of malloc will be a void pointer containing the memory address of the first byte of allocated space. Upon assigning this value to testArray, it will be type-casted to the assigned variable type (struct array *). Now you can use pointer arithmetic to access a specific index i with *(testArray + i), or simply testArray[i]. If you find that N was not a sufficient size, you can use realloc to increase the array size to 2N, or whatever size deemed necessary.
struct array* testArray = (array*)malloc(sizeof(testArray));
is a little wrong as you only allocate 1 element of testArray.
It is more like:
struct A
{
int a;
int b;
....
};
struct A* arr = malloc( N * sizeof(struct A) );
^^^
N element of struct A
int j;
for (j=0; j<N; ++j) // Iterate it like any other array
{
arr[j].a = 5;
arr[j].b = 42;
....
}
Use realloc when you need the array to grow.
When reading from a file/stdin it could look like (based on comment from David C. Rankin):
int n=0; // Count of the number of structs read from the file
struct A* arr = malloc( N * sizeof(struct A) );
while (read line from file)
{
arr[n].a = val1;
arr[n].b = val2;
++n; // Increment count
if (n == N) // Check if current array is full, i.e. realloc needed
{
// realloc array to 2 * N; N = N * 2
}
}

should i allocate memory inside a function or place function has been called

Let's suppose I am passing a pointer to an array or a structure to a function.
Like
myfun1(struct node *head, int* arr, int N){
head = malloc(sizeof head);
arr = malloc(N* sizeof arr);
......
}
myfun2(struct node *head, int* arr){
...
}
And I am calling these functions from another function
void CallingFunction(void){
struct node* head1 = NULL;
int *arr1;
struct node* head2 = NULL;
int *arr2;
int N = 10;
head2 = malloc(sizeof head);
arr2 = malloc(N* sizeof arr);
myfunc1(head1, arr1, N);
myfunc2(head2, arr2);
}
Which method of calling a function is better. myfun1 or myfun2 ?
Should I allocate memory to structure and array from CallingFunction or inside function ?
EDIT:
As pointed out, program has some mistakes, let's say I correct these two mistakes.
head = malloc(sizeof *head);
myfunc2(head2, arr2, N);
Now, what would be the answer. should I allocation memory inside callingFunction() or myfun().
The first is a memory leak (besides the wrong sizeof head and sizeof arr). You have to pass struct node ** to set the function parameters.
The second is better (besides not getting the size of arr) : It does not hide memory allocation and leads to proper pairing of malloc/free inside the calling function.
head = malloc(sizeof head);
is wrong, you want to reserve space with the size of an object, not with the size of a pointer to this object, change to:
head = malloc(sizeof *head);
Which method of calling a function is better. myfun1 or myfun2 ?
You can not reserve space for an array without knowing how many elements, myfun2 doesn't works.
Both approaches are correct and choosing the best option depends on what the lifecycle of the allocated block will be; it's important to pair memory allocation and release operations. If that memory is only going to be used inside the myfun1()/myfun2() context, I would recommend allocating and releasing it there. However, if it will persist and be used in other parts of the program, it would be better to make it very obvious where memory is allocated and released rather than have it be a side effect of some other operation.
Also, I would recommend always using sizeof(struct node) and sizeof(int) instead of sizeof(*head) and sizeof(*arr). It's much clearer and prevents the kind of mistakes others have pointed out in your original code.
In the context of myfun1(), sizeof(head) gives you the size of a pointer to a struct whereas sizeof(*head) gives you the size of the struct itself, which is what you want in this case.
Likewise, sizeof(arr) gives you the size of a pointer to an int and sizeof(*arr) gives you the size of a single int.
Using the sizeof operand with arrays has yet another caveat: its behaviour depends on the context in which the array was declared and whether it's allocated on the stack or on the heap.
Here's a small program that exemplifies this. Pay particular attention to sizeof(stackArray) when used within the same context in which the array was declared.
#include <stdio.h>
#include <stdlib.h>
#define N 10
void aux(int *stackArray, int *heapArray) {
printf("\nIn a different context:\n");
printf("sizeof(*stackArray) == sizeof(int): %zu\n", sizeof(*stackArray));
printf("sizeof(*heapArray) == sizeof(int): %zu\n", sizeof(*heapArray));
printf("sizeof(stackArray) == sizeof(int *): %zu\n", sizeof(stackArray));
printf("sizeof(heapArray) == sizeof(int *): %zu\n", sizeof(heapArray));
}
int main() {
int stackArray[N];
int *heapArray = malloc(N * sizeof(int));
printf("In the context in which they were declared/allocated:\n");
printf("sizeof(*stackArray) == sizeof(int): %zu\n", sizeof(*stackArray));
printf("sizeof(*heapArray) == sizeof(int): %zu\n", sizeof(*heapArray));
printf("sizeof(stackArray) == N * sizeof(int): %zu\n", sizeof(stackArray));
printf("sizeof(heapArray) == sizeof(int *): %zu\n", sizeof(heapArray));
aux(stackArray, heapArray);
free(heapArray);
return 0;
}
The output of that program in my machine is:
In the context in which they were declared/allocated:
sizeof(*stackArray) == sizeof(int): 4
sizeof(*heapArray) == sizeof(int): 4
sizeof(stackArray) == N * sizeof(int): 40
sizeof(heapArray) == sizeof(int *): 8
In a different context:
sizeof(*stackArray) == sizeof(int): 4
sizeof(*heapArray) == sizeof(int): 4
sizeof(stackArray) == sizeof(int *): 8
sizeof(heapArray) == sizeof(int *): 8
In short, if you always use sizeof() with the types you want instead of variable names, you don't need to worry about these things.
arr2 = malloc(N* sizeof arr);
I recommend to use calloc instead of doing a multiplication inside malloc argument:
Example:
arr2 = calloc(N, sizeof(*arr));
Normally myfunc2 is preferred unless the function is a wrapper to allocate something, in which case another function to deallocate memory exist.

How to change the size of a struct using malloc

I am making a struct with undefined size.
#define namemax 128
struct Image{
char name[namemax+1];
int length;
double *array; //double array[256]
};
struct Image* graph;
graph=malloc(max*sizeof(struct Image));
If I define array[256], everything work fine.
but if I use double *array, and then write
graph[check].array = malloc( 100 * sizeof(double *));
it creates a segment fault.
I was wondering how can I define the size using malloc and realloc for array.
If I add value in the array, it shows segment fault.
struct Image* graph;//outside the while loop
while: //it is inside the while loop
//basically it read different name each line, and put the x and y to the array
graph[check].array = malloc( 100 * sizeof(double));
check++;
strcpy( graph[check].name,type);
graph[check].array[count]=shiftX;
graph[check].array[count+1]=shiftY;
That because double * array is declaring a pointer to an array, not storage. You want to declare storage here. The easiest way is to simply define the array as double array[1] and make sure it's the last element in the struct. You can then allocate space for the structure using malloc() and realloc() by passing them the size of the base struct plus the size of the array (sizeof double * the number of array elements).
One problem I see is using sizeof(double *) instead of sizeof(double) even if both are the same if you're using x86-64 architecture.
i think it makes seg fault because in malloc you have said sizeof(double *) (Actually you declare an array of array).
Just try to say sizeof(double) it may work but I dont know that for sure because I haven't tested it.
And by the way when you declare array staticly you reserve space for it when you declare your struct variable but when you declare it as pointer ( dynamic array ) you should reserve space for it and you can change the array's size. You should use realloc google it.

How should I malloc/realloc with a struct that includes an array?

I'm pretty new to c, so if my steps are wrong, please let me know. Let's say that I have something like the following:
struct graphNode{
int val;
graphNode* parent;
int succSize;
int succMaxSize;
graphNode* succ[1];
};
I will create a new node with:
graphNode *n;
n = malloc(sizeof(struct graphNode));
assert(n);
n->val = 1;
n->parent = NULL;
n->succSize = 0;
n->succMaxSize = 1;
Then, if I want to add a successor to the node
if (n->succSize == n->succMaxSize){
n->succ = realloc(n->succ, sizeof(graphNode*) * n->succMaxSize * 2);
n->succMaxSize *= 2;
}
n->succ[succSize] = n2; //n2 is of type graphNode*
succSize++;
Is this correct? Do I need to realloc for the struct as well or is realloc of the array enough? Do I need to malloc for the initial array? Should the initial array size be included in my malloc call for n?
The usual way to define a "stretchy" array member in C is to either specify a size of 0 or no size at all, e.g.:
struct foo {
int stuff;
bar theBars[]; // or theBars[0]
};
With this definition, sizeof(struct foo) will include all the elements other than the array at the end, and you can allocate the right size by saying malloc(sizeof(struct foo) + numberOfBars * sizeof(bar)).
If you need to reallocate it to change the number of bar elements, then you'll use the same formula (but with a new numberOfBars).
To be clear, you can't just realloc part of a struct. You have to realloc the whole thing.
realloc(ptr,size) needs 2 parameters, not 1 as used in realloc(sizeof(graphNode*) * n->succMaxSize * 2)
// Something like ...
graphNode *n;
n->succSize = 0;
n->succMaxSize = 0; // set to 0
n->succ = NULL; // Initialize to NULL
// Then, if OP wants to add a successor to the node
if (n->succSize <= n->succMaxSize){
n->succ = realloc(n->succ, sizeof(graphNode*) * n->succMaxSize * 2);
n->succMaxSize *= 2;
}
n->succ[succSize++] = n2;
As with all memory allocations, check for NULL return. In realloc(), one should save the original value, so if the realloc() fails, the original pointer is not lost.
Usually when you see struct definition where the last field is an array of size 0 or 1 it means the author is going to do some subtle stuff with malloc when the struct is malloced.
For example
struct foo {
int x;
:
:
type a[0];
};
With a malloc like
struct foo *p = malloc(sizeof(*p) + (n * sizeof(type));
What this does is it allocates a contiguous chunk of memory for the struct and the trailing array. In this case the array size is n. So references to the array in this case are:
p->a[i] // where i >= 0 and i < n
One reason for doing this is to save memory.
I'm sure there are better explanations for this on StackOver; it's a very common C idiom.
It's generally not used when the array is dynamic. Rather, it is used when the array size is known at malloc() time. You can use dynamically, of course, but you have to realloc the entire memory chunk, not just the struct or array by itself. To increase the size to 2n you would say
p = realloc(p, sizeof(*p) + (2 * n * sizeof(type)));
Now your array is twice is big as it was, and it's still one chunk of memory.
If you only want a single array, just make succ a single pointer and only use malloc/realloc etc. to allocate memory for the array.
graphNode* succ;
What you are doing is almost certain to break.
I too am new to C, but there's some things that I can see right off the bat. First of all, you can't re-allocate arrays. In c89, they're compile-time fixed-size. In C99 and C11, they can be dynamically allocated, but not reallocated (as far as I'm aware). So for this, you need to allocate a
graphnode *succ;
pointer, and malloc(nodes * sizeof(node)).
graphNode* succ[1];
This creates an array of size one, not an array with a maximum index of one. So, it is the same (almost) functionally as
graphNode* succ;
except that you can't change its size once you've made it.
I think what you want is to make a tree, with a dynamically re-allocable amount of branches. In this case, you only need to reallocate the size of the graphNode* pointer, and then access each element via index as you would an array.

Are "malloc(sizeof(struct a *))" and "malloc(sizeof(struct a))" the same?

This question is a continuation of Malloc call crashing, but works elsewhere
I tried the following program and I found it working (i.e. not crashing - and this was mentioned in the above mentioned link too). I May be lucky to have it working but I'm looking for a reasonable explanation from the SO experts on why this is working?!
Here are some basic understanding on allocation of memory using malloc() w.r.t structures and pointers
malloc(sizeof(struct a) * n) allocates n number of type struct a elements. And, this memory location can be stored and accessed using a pointer-to-type-"struct a". Basically a struct a *.
malloc(sizeof(struct a *) * n) allocates n number of type struct a * elements. Each element can then point to elements of type struct a. Basically malloc(sizeof(struct a *) * n) allocates an array(n-elements)-of-pointers-to-type-"struct a". And, the allocated memory location can be stored and accessed using a pointer-to-(pointer-to-"struct a"). Basically a struct a **.
So when we create an array(n-elements)-of-pointers-to-type-"struct a", is it
valid to assign that to struct a * instead of struct a ** ?
valid to access/de-reference the allocated array(n-elements)-of-pointers-to-type-"struct a" using pointer-to-"struct a" ?
data * array = NULL;
if ((array = (data *)malloc(sizeof(data *) * n)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
The code snippet is as follows:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
typedef struct {
int value1;
int value2;
}data;
int n = 1000;
int i;
int val=0;
data * array = NULL;
if ((array = (data *)malloc(sizeof(data *) * n)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
printf("allocation successful\n");
for (i=0 ; i<n ; i++) {
array[i].value1 = val++;
array[i].value2 = val++;
}
for (i=0 ; i<n ; i++) {
printf("%3d %3d %3d\n", i, array[i].value1, array[i].value2);
}
free(array);
printf("freeing successful\n");
return 0;
}
EDIT:
OK say if I do the following by mistake
data * array = NULL;
if ((array = (data *)malloc(sizeof(data *) * n)) == NULL) {
Is there a way to capture (during compile-time using any GCC flags) these kind of unintended programming typo's which could work at times and might blow out anytime! I compiled this using -Wall and found no warnings!
There seems to be a fundamental misunderstanding.
malloc(sizeof(struct a) * n) allocates n number of type struct a elements.
No, that's just what one usually does use it as after such a call. malloc(size) allocates a memory region of size bytes. What you do with that region is entirely up to you. The only thing that matters is that you don't overstep the limits of the allocated memory. Assuming 4 byte float and int and 8 byte double, after a successful malloc(100*sizeof(float));, you can use the first 120 of the 400 bytes as an array of 15 doubles, the next 120 as an array of 30 floats, then place an array of 20 chars right behind that and fill up the remaining 140 bytes with 35 ints if you wish. That's perfectly harmless defined behaviour.
malloc returns a void*, which can be implicitly cast to a pointer of any type, so
some_type **array = malloc(100 * sizeof(data *)); // intentionally unrelated types
is perfectly fine, it might just not be the amount of memory you wanted. In this case it very likely is, because pointers tend to have the same size regardless of what they're pointing to.
More likely to give you the wrong amount of memory is
data *array = malloc(n * sizeof(data*));
as you had it. If you use the allocated piece of memory as an array of n elements of type data, there are three possibilities
sizeof(data) < sizeof(data*). Then your only problem is that you're wasting some space.
sizeof(data) == sizeof(data*). Everything's fine, no space wasted, as if you had no typo at all.
sizeof(data) > sizeof(data*). Then you'll access memory you shouldn't have accessed when touching later array elements, which is undefined behaviour. Depending on various things, that could consistently work as if your code was correct, immediately crash with a segfault or anything in between (technically it could behave in a manner that cannot meaningfully be placed between those two, but that would be unusual).
If you intentionally do that, knowing point 1. or 2. applies, it's bad practice, but not an error. If you do it unintentionally, it is an error regardless of which point applies, harmless but hard to find while 1. or 2. applies, harmful but normally easier to detect in case of 3.
In your examples. data was 4 resp. 8 bytes (probably), which on a 64-bit system puts them into 1. resp. 2. with high probability, on a 32-bit system into 2 resp. 3.
The recommended way to avoid such errors is to
type *pointer = malloc(num_elems * sizeof(*pointer));
No.
sizeof(struct a*) is the size of a pointer.
sizeof(struct a) is the size of the entire struct.
This array = (data *)malloc(sizeof(data *) * n) allocates a sizeof(data*) (pointer) to struct data, if you want to do that, you need a your array to be a data** array.
In your case you want your pointer to point to sizeof(data), a structure in memory, not to another pointer. That would require a data** (pointer to pointer).
is it valid to assign that to struct a * instead of struct a ** ?
Well, technically speaking, it is valid to assign like that, but it is wrong (UB) to dereference such pointer. You don't want to do this.
valid to access/de-reference the allocated array(n-elements)-of-pointers-to-type-"struct a" using pointer-to-"struct a" ?
No, undefined behavior.

Resources