qsort() doesn't sort data from structure - c

I've got a structure:
typedef struct personalData
{
char name[20];
char * remarks;
int age;
float weight;
} personalData;
I need to sort data by weight using qsort(). Here's my weightSort function:
void weightSort(personalData * data[], int len)
{
qsort(data, len, sizeof(struct personalData *), structSortWeight);
}
where len = 10(calculated before using some different functions, but it probably doesn't matter), data[] is defined in main():
struct personalData * data[10];
and finally structSortWeight:
int structSortWeight(const void *a, const void *b)
{
personalData *p1 = (personalData *)a;
personalData *p2 = (personalData *)b;
return (p1->weight - p2->weight);
}
My program crashes when it starts sorting. I want to add that when I change the third argument in qsort() to sizeof(float) it doesn't crash but p1->weight and p2->weight point to some rubbish.
The calling function in main():
weightSort(data, len);
personalData * data[] has some data already assigned.

This array declaration:
struct personalData * data[10];
does not declare an object suitable for use as the first parameter to
void weightSort(personalData data[], int len)
The variable and function parameter have different levels of indirection. Your actual data is an array of pointers to struct personalData, whereas the function parameter is appropriate for an array of the structures themselves. This produces undefined behavior. Probably more functionally relevant, the item size that you pass to qsort() is therefore incorrect: with the data as declared in main(), you want as item size not the size of struct personalData, but rather the size of a pointer to one (sizeof(struct personalData *)).
Furthermore, your comparison function is wrong. In the first place, it must return an int, not a float, but in the second place, since the elements you are sorting are pointers to structures, the arguments presented to the comparison function will be pointers to such pointers. You treat them instead as pointers directly to structures.

Your comparison function receives pointers to two elements of the list, each of which is also a pointer. So the real type of each parameter is personalData **, but you cast them to personalData *. So you're treating a pointer as a structure instance, which is why you're seeing garbage.
You need to add an additional level of indirection in your comparison function:
int structSortWeight(const void *a, const void *b)
{
// no need to cast from void *
const personalData **p1 = a;
const personalData **p2 = b;
return ((*p1)->weight - (*p2)->weight);
}

The signature for the qsort comparison function is
int (*comp)(const void *, const void *)
Returning a float does not work at all.

return (p1->weight - p2->weight); is not a suitable compare. This subtracts 2 float values and converts to int. The compare function must return the sensible consistent results.
Consider weights A,B,C: 1.1, 2.0, 2.9.
Comparing f(A,B) returns int 0.
Comparing f(B,C) returns int 0.
Comparing f(A,C) returns int 1. // This does not make sense if A==B and B==C
This inconsistency can fool qsort() resulting in undefined behavior (UB).
A better compare function
int structSortWeight2(const void *a, const void *b) {
const personalData **p1 = (const personalData **)a;
const personalData **p2 = (const personalData **)b;
// 2 compares are done, each returning an `int`
return ((*p1)->weight > (*p2)->weight) - ((*p1)->weight < (*p2)->weight);
}
Code has other issues as detailed in #John Bollinger

Related

qsort with typedef structs in C

After searching in lots of posts, I cannot solve my problem. I want to order an array of structs depending on one field (deadline):
typedef struct{
int ident;
int computation;
int period;
int deadline;
}task_t;
task_t *tasks;
int compare(const void *a, const void *b) {
task_t *ia = *(task_t**)a;
task_t *ib = *(task_t**)b;
//task_t *ia = (task_t *)a;
//task_t *ib = (task_t *)b;
return (ia->deadline - ib->deadline);
}
//Randomly generation of parameters of tasks
fprintf(stderr,"before:\n");
for (i=0;i<nT;i++){
fprintf(stderr,"%d;%d;%d;%d\n", tasks[i].ident, tasks[i].computation, tasks[i].deadline,tasks[i].period);
}
size_t size = sizeof(tasks) / sizeof(task_t*);
qsort(tasks, size, sizeof(task_t *), compare);
fprintf(stderr,"\after:\n");
for (i=0;i<nT;i++){
fprintf(stderr,"%d;%d;%d;%d\n", tasks[i].ident, tasks[i].computation, tasks[i].deadline,tasks[i].period);
}
Before and after qsort, the result is the same. I think the problem is the pointer but I don't know how to solve it. I have tried a lot of combinations qsort(&tasks, size, sizeof(task_t *), &compare);
and also inside compare function, but the result does not change. Could you help me? Sorry if the question is so many repeated.
size_t size = sizeof(tasks) / sizeof(task_t*);
only works if tasks is an array of task_t*. It isn't, it's a pointer to task_t (presumably to an array of task_t, but not one with compile-time size). You can't use sizeof in that case, you just have to know how big the array is in some other way. As is, you basically asked qsort to sort an array with one element in it.
You've also written your comparator wrong; if the array is of task_ts, then the void*s it receives are really pointers to task_t, not double pointers to task_t. So you'll need to change:
task_t *ia = *(task_t**)a;
task_t *ib = *(task_t**)b;
to:
const task_t *ia = a;
const task_t *ib = b;
Lastly, you need to pass sizeof(task_t) to qsort, not sizeof(task_t *); again, the array is of task_t, not task_t*.

C, assignment of struct pointers changes the content of the right side of assignment

I have the following structs:
typedef struct{
char *name;
int size;
void *data;
} Struct1;
typedef struct st2{
char *name;
struct st2 **Struct2array;
Struct1 **Struct1array;
int Struct1_n;
int Struct2_n;
} Struct2;
where the double pointers in Struct2 are used as dynamic arrays of pointers to other Struct2's or Struct1's. The data in Struct1 is used as a dynamic array to store some data. Struct1_n and Struct2_n represent the number of elements inside of their respective dynamic arrays.
When I make a variable of type Struct1, I fill the data by casting a char * to a void * and using memcpy to copy it into data. If I then cast to data back into a char pointer, I can get back the contents and they are generally the same. However, for some reason the values that data in Struct1 is pointing to change after the following line:
struct2pointer->Struct1array[struct2pointer->Struct1_n - 1] = struct1pointer;
Examples:
printf("%d\n", *(char *)(struct1pointer->data));
gives the value of the 1stbyte of struct1pointer->data as -96 immediately after the problematic line regardless of the value it printed immediately before(which was the same one memcpy-d into data). if I add 1 to the pointer before casting it to a char pointer(2nd byte) it always gives 32, if I add 2 (3rd byte)it always gives 96 and so on.
Why is this happening when the struct1pointer is on the right side of the assignment operator and what can be done to fix this?
EDIT:
Functions where content changes:
void struct2_addstruct1(Struct2 struct2pointer, Struct1 *struct1pointer){
struct2->Struct1_n++;
struct2pointer->Struct1array = realloc(struct2pointer->Struct1array, struct2->Struct1_n * sizeof(Struct1 *)); //edited to remove increment that was added on accident, isn't in the original code
struct2pointer->Struct1array[struct2pointer->Struct1_n - 1] = struct1pointer;
}
The function that creates Struct1:
void struct1_init(Struct1 *s, char *name, void *data, int size){
s->name = malloc(strlen(name) + 1);
strcpy(s->name, name);
s->size = size;
s->data = malloc(size);
memcpy(s->data, data, size);
}
This is how that funcion is called when creating struct1:
Struct1 *s;
struct1_init(s, name, data, size);
name, data and size are provided form the outside but shouldn't have anything to do with the problem.
Look at this code:
Struct1 *s;
struct1_init(s, name, data, size);
Here s is uninitialized.
However in struct1_init function you do assume that the pointer s is already pointing to a Struct1.
Maybe you forgot a malloc - like:
Struct1 *s = malloc(sizeof *s);
struct1_init(s, name, data, size);

Is it possible to get the size of the item the pointer is pointing at?

Is it possible to find the size of item_t through the pointer?
typedef struct item
{
char x;
char y;
char life;
}item_t;
void main (void)
{
item_t test;
void *ptr = &test;
printf("%d\n",sizeof(ptr));
}
return: 8
Not if ptr is of type void* -- but it probably shouldn't be.
You can't dereference a void* pointer. You can convert it to some other pointer type and dereference the result of the conversion. That can sometimes be useful, but more often you should just define the pointer with the correct type in the first place.
If you want a pointer to an item_t object, use an item_t* pointer:
item_t test;
item_t *ptr = &test;
printf("%zu\n", sizeof(*ptr));
This will give you the size of a single item_t object, because that's the type that ptr points to. If ptr is uninitialized, or is a null pointer, you'll get the same result, because the operand of sizeof is not evaluated (with one exception that doesn't apply here). If ptr was initialized to point to the initial element of an array of item_t objects:
ptr = malloc(42 * sizeof *ptr);
sizeof *ptr will still only give you the size of one of them.
The sizeof operator is (usually) evaluated at compile time. It uses only information that's available to the compiler. No run-time calculation is performed. (The exception is an operand whose type is a variable-length array.)
The correct format for printing a value of type size_t (such as the result of sizeof) is %zu, not %d.
And void main(void) should be int main(void) (unless you have a very good reason to use a non-standard definition -- which you almost certainly don't). If a book told you to define main with a return type of void, get a better book; its author doesn't know C very well.
Short answer: no. Given only ptr, all you have is an address (answer by WhozCraig).
Longer answer: you can implement inheritance by having the first field in all your structs specify its size. For example:
struct something_that_has_size
{
size_t size;
};
struct item
{
size_t size;
char x;
char y;
char life;
};
struct item2
{
size_t size;
char x;
char y;
char z;
char life;
};
// Somewhere in your code
...
struct item *i1 = malloc(sizeof(struct item));
i1->size = sizeof(struct item); // you are telling yourself what the size is
struct item2 *i2 = malloc(sizeof(struct item2));
i2->size = sizeof(struct item2);
// Later in your code
void *ptr = ... // get a pointer somehow
size_t size = ((struct something_that_has_size*)ptr)->size; // here is your size
But instead of size, you should better record the type of your struct - it's more useful than just the size. This technique is called discriminated union.
You can only cast a void pointer to get what is behind in the correct type, you cannot dereference it directly.
#include <stdio.h>
#include <stdlib.h>
typedef struct item {
char x;
char y;
char life;
} item_t;
int main()
{
item_t test;
void *ptr = &test;
printf("%zu %zu\n", sizeof(*(item_t *) ptr), sizeof(item_t));
exit(EXIT_SUCCESS);;
}
But that is of not much use because you need to know the type in the first place and have won nothing.
TL;DR: no, not possible

Casting function pointers

I am writing a function that receives a pointer to a comparison function and an array of MyStructs and is supposed to sort the array according to the comparison function:
void myStructSort(
struct MyStruct *arr,
int size,
int (*comp)(const struct MyStruct *, const struct MyStruct *)) {
qsort(arr, size, sizeof(struct MyStruct), comp);
}
Unfortunately this doesn't compile because qsort expects the comparator to receive void * arguments and not const struct MyStruct *. I thought of several bad solutions and was wondering what the correct solution is.
Option 1
Cast comp to int (*)(const void *, const void*). This compiles but is undefined behavior (see this SO question).
Option 2
Create a global variable int (*global_comp)(const struct MyStruct *, const struct MyStruct *) and set global_comp=comp inside myStructSort. Then create a function:
int delegatingComp(const void *a, const void *b) {
return globalComp((const struct MyStruct *)a, (const struct MyStruct *)b);
}
And in myStructSort call qsort(arr, size, sizeof(struct MyStruct), delegatingComp). The problem with this is the icky global variable.
Option 3
Reimplement qsort. This is functionally safe but very bad practice.
Is there a magical perfect fourth option?
Edit
I can't change the API of myStructSort and I am compiling my code using gcc c99 -Wall -Wextra -Wvla.
Option 2 breaks thread-safety, so I wouldn't choose that one.
Option 3 is just plain wrong as you point out. There is no reason to re-implement quicksort and potentially make a mistake.
Option 1 is UB but it will work on any sane compiler. If you choose this option be sure to add a comment.
I would also consider:
Option 4. Redesign the interface of myStructSort to take int (*)(const void *, const void*) or scrap it entirely and call qsort directly. Basically send it back to the architecht, because he made a poor design choice.
following approach only works for gcc. It's a part of gnu extension. further please reference to https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Nested-Functions.html#Nested-Functions
first let's make sure the prototype of qsort is in such a form:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
then you can:
void myStructSort(
struct MyStruct *arr,
int size,
int (*comp)(const struct MyStruct *, const struct MyStruct *)) {
int comparator(const void * a, const void *b) {
return comp((const struct MyStruct *)a, (const struct MyStruct *)b);
}
qsort(arr, size, sizeof *arr, comparator);
}
But again, since it uses gnu extension, don't expect too much portability.
ABOUT YOUR COMMENT: for modern gcc, gnu standard is default instead of iso ones. specifically, lastest gcc should use gnu11 standard. older ones are using gnu89. so, I don't know about your command line params, but if -std is not set, this will work.
following is an example taken from info gcc, just in case the link is dead. it shows a closure-like usage of nested function:
bar (int *array, int offset, int size)
{
int access (int *array, int index)
{ return array[index + offset]; }
int i;
/* ... */
for (i = 0; i < size; i++)
/* ... */ access (array, i) /* ... */
}
If you are using gcc, then you can use the qsort_r function in glibc since 2.8, which allows you to specify a comparator function with an additional user-supplied argument:
void qsort_r(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *, void *),
void *arg);
This is not portable, of course, and it requires you to define the feature-test macro:
#define _GNU_SOURCE
(On FreeBSD -- and, presumably, Mac OS X -- there is a similar but incompatible qsort_r; the difference is that the user-supplied context argument is provided as the first argument to the comparison function, rather than the last argument.)
But if you have it, it allows you to avoid the global in option 2:
/* This struct avoids the issue of casting a function pointer to
* a void*, which is not guaranteed to work. It might not be
* necessary, but I know of no guarantees.
*/
typedef struct CompContainer {
int (*comp_func)(const struct MyStruct *, const struct MyStruct *);
} CompContainer;
int delegatingComp(const void *a, const void *b, void* comp) {
return ((CompContainer*)comp)->comp_func((const struct MyStruct *)a,
(const struct MyStruct *)b);
}
void myStructSort(
struct MyStruct *arr,
int size,
int (*comp_func)(const struct MyStruct *,
const struct MyStruct *)) {
const CompContainer comp = {comp_func};
qsort_r(arr, size, sizeof(struct MyStruct), delegatingComp, &comp);
}
(Live on ideone)
The correct approach is to cast from void const * to MyStruct const * in the comparison function.
This is well-defined for the first object, because the pointer that was passed to the comparison function was created by a cast from MyStruct const * to void const *, and casting a pointer to void back to its original type is allowed (and it's really the only thing that is).
For the other array members, it is assumed that casting void const * to char const *, adding the offset of the object, generated by multiplying the object size with the position of the object in the array, and casting that back to void const * will give a pointer that can be cast back to MyStruct const *.
That is a bold assumption, but usually works out. There may be corner cases where this doesn't work, but in general compilers pad any struct foo to a multiple of its alignment to ensure that array members' start addresses have a distance of sizeof(struct foo).
Casting function pointers is generally unsafe and needs to be avoided, as different data types may have different representations -- for example, a void * must be able to express every possible address as it could have been converted from a char *, while a MyStruct * is guaranteed to have a few of the least significant bits clear as any valid object would be aligned -- so it is entirely possible that the calling convention for these types could be different.
The only sane option is to re-write the interface you've created, or make a new one.
I've done something very similar with bubble sort on another answer of mine.
In short, with C, you want your sort function to be of the form:
void* bubbleSort(void* arr, int (*compareFcn)(void*, void*),
size_t sizeOfElement, size_t numElements)
And your comparison function to be of the form:
int compareFunction(void *a, void *b);

function prototype with void* parameter

I have two functions, each taking a pointer to a different type:
void processA(A *);
void processB(B *);
Is there a function pointer type that would be able to hold a pointer to either function without casting?
I tried to use
typedef void(*processor_t)(void*);
processor_t Ps[] = {processA, processB};
but it didn't work (compiler complains about incompatible pointer initialization).
Edit: Another part of code would iterate through the entries of Ps, without knowing the types. This code would be passing a char* as a parameter. Like this:
Ps[i](data_pointers[j]);
Edit: Thanks everyone. In the end, I will probably use something like this:
void processA(void*);
void processB(void*);
typedef void(*processor_t)(void*);
processor_t Ps[] = {processA, processB};
...
void processA(void *arg)
{
A *data = arg;
...
}
If you typedef void (*processor_t)(); then this will compile in C. This is because an empty argument list leaves the number and types of arguments to a function unspecified, so this typedef just defines a type which is "pointer to function returning void, taking an unspecified number of arguments of unspecified type."
Edit: Incidentally, you don't need the ampersands in front of the function names in the initializer list. In C, a function name in that context decays to a pointer to the function.
It works if you cast them
processor_t Ps[] = {(processor_t)processA, (processor_t)processB};
By the way, if your code is ridden with this type of things and switch's all over the place to figure out which function you need to call, you might want to take a look at object oriented programming. I personally don't like it much (especially C++...), but it does make a good job removing this kind of code with virtual inheritance.
This can be done without casts by using a union:
typedef struct A A;
typedef struct B B;
void processA(A *);
void processB(B *);
typedef union { void (*A)(A *); void (*B)(B *); } U;
U Ps[] = { {.A = processA}, {.B = processB} };
int main(void)
{
Ps[0].A(0); // 0 used for example; normally you would supply a pointer to an A.
Ps[1].B(0); // 0 used for example; normally you would supply a pointer to a B.
return 0;
}
You must call the function using the correct member name; this method only allows you to store one pointer or the other in each array element, not to perform weird function aliasing.
Another alternative is to use proxy functions that do have the type needed when calling with a parameter that is a pointer to char and that call the actual function with its proper type:
typedef struct A A;
typedef struct B B;
void processA(A *);
void processB(B *);
typedef void (*processor_t)();
void processAproxy(char *A) { processA(A); }
void processBproxy(char *B) { processB(B); }
processor_t Ps[] = { processAproxy, processBproxy };
int main(void)
{
char *a = (char *) address of some A object;
char *b = (char *) address of some B object;
Ps[0](a);
Ps[1](b);
return 0;
}
I used char * above since you stated you are using it, but I would generally prefer void *.

Resources