I have the following struct definition
typedef struct {
char* name;
int address;
line_type_t type; /* an enum */
} label_t;
typedef struct {
int count;
int max;
label_t** head;
} label_registry_t;
I'm trying to search it like so:
int label_cmp(const void* v1, const void* v2) {
label_t* l1 = (label_t*) v1;
label_t* l2 = (label_t*) v2;
return strcmp(l1->name, l2->name);
}
label_t* registry_find(label_registry_t* registry, char* name) {
label_t** result;
label_t label;
label.name = name;
result = bsearch(&label, registry->head, registry->count, sizeof(label_t*), &label_cmp);
if (result == NULL) {
return NULL;
}
return *result;
}
It is not successful. When I debug in label_cmp, I see the first argument is the name I expect, but the second is jibbrish. Looking at addresses, I see that v2 is 0x804e008, while registry->head is shown as 0x804e018 (actually, the debugger shows registry->head as 0x804e008, but then under it *head as 0x804e018).
So I imagine this has to do with word alignment, but I can't find a way to pass the right address to bsearch. I tried registry->head + 0 and ®istry->head[0].
So what is the right way to use bsearch here?
If you want to find an X, you pass to bsearch an array of X [1] and an address of an X, and your comparison function accepts two addresses of X. To recap:
If you want to find an int, you pass to bsearch an array of int and an address of an int, and your comparison function accepts two addresses of int.
If you want to find a struct, you pass to bsearch an array of struct and an address of a struct, and your comparison function accepts two addresses of struct.
If you want to find a pointer to struct, you pass to bsearch an array of pointers to struct and an address of a pointer to struct, and your comparison function accepts two addresses of pointer to struct.
Now what your code has is an array of pointers to struct, and address of a struct, and a comparison function that accepts two addresses of struct. This ain't gonna work. You need to harmonise the inputs.
--
[1] An address of its first element actually, but it is not important here.
Related
After passing a void* pointer as argument to a function, is there a way to specify the type to which it is cast as another parameter. If I have two structs like:
struct A{
int key;
char c;
}
struct B {
int key;
float d;
}
Is it possible to define a function,
void func(void * ptr, ...){
//operate on key
}
and pass a pointer to either structs to the function after casting to void* and access the key element from within the function.
Trying to understand the use of void*, how structure definitions are stored ( How are the offsets of various elements determined from the structure definition? ) and how ploymorphism may be implemented in c.
Was trying to see if I could write Binary Search tree functions that could deal with nodes of any struct.
After passing a void* pointer as argument to a function, is there a way to specify the type to which it is cast as another parameter.
Yes and no.
I suppose you're hoping for something specific to this purpose, such as a variable that conveys a type name that the function can somehow use to perform the cast. Something along the lines of a type parameter in a C++ template, or a Java generic method, for example. C does not have any such thing.
But of course, you can use an ordinary integer to convey a code representing which of several known-in-advance types to cast to. If you like, you can even use an enum to give those codes meaningful names. For example:
enum arg_type { STRUCT_A_TYPE, STRUCT_B_TYPE };
void func(void *ptr, enum arg_type type) {
int key = 0;
switch (type) {
case STRUCT_A_TYPE:
key = ((struct A *) ptr)->key;
break;
case STRUCT_B_TYPE:
key = ((struct B *) ptr)->key;
break;
default:
assert(0);
}
// ...
}
Note well that that approach allows accessing any member of the pointed-to structure, but if you only want to access the first member, and it has the same type in every structure type of interest, then you don't need to know the specific structure type. In that particular case, you can cast directly to the member type:
void func(void *ptr) {
int key = *(int *)ptr;
// ...
}
That relies on C's guarantee that a pointer to any structure, suitably cast, points to that structure's first member.
Trying to understand the use of void*, how structure definitions are store and how ploymorphism may be implemented in c.
That's awfully broad.
C does not offer polymorphism as a language feature, and C objects do not carry information about their type such as could be used to dispatch type-specific functions. You can, of course, implement that yourself, but it is non-trivial. Available approaches include, but are not limited to,
passing pointers to functions that do the right thing for the type of your data. The standard qsort() and bsearch() functions are the canonical examples of this approach.
putting some kind of descriptor object as the first member of every (structure) type. The type of that member can be a structure type itself, so it can convey arbitrarily complex data. Such as a vtable. As long as it is the first member of all your polymorphic structures, you can always access it from a pointer to one of them by casting to its type, as discussed above.
Using tagged unions of groups of polymorphic types (requiring that all the type alternatives in each group be known at build time). C then allows you to look at any members of the common initial sequence of all union members without knowing which member actually has a value. That initial sequence would ordinarily include the tag, so that you don't have to pass it separately, but it might include other information as well.
Polymorphism via (single-)inheritance can be implemented by giving each child type an object of its parent type as its first member. That then allows you to cast to (a pointer to) any supertype and get the right thing.
Lets say you had a sort function that takes a function as a parameter which implements the "compare" functionality of the sort. The sort would then be capable of sorting a list of any arbitrary struct, by handing it a comparer function that implements the correct order for your particular struct.
void bubbleSort(Node* start, bool comparerFunction(void* a, void* b))
Consider the following struct definition:
typedef struct {
int book_id;
char title[50];
char author[50];
char subject[100];
char ISBN[13];
} Book;
And this unremarkable linked list definition:
typedef struct node{
void* item;
struct node* next;
} Node;
Which can store an arbitrary struct in the item member.
Because you know the type of the members you've placed in your linked list, you can write a comparer function that will do the right thing:
bool sortByTitle(void* left, void* right) {
Book* a = (Book*)left;
Book* b = (Book*)right;
return strcmp(a->title, b->title) > 0;
}
And then call your sort like this:
bubbleSort(myList, sortByTitle);
For completeness, here is the bubbleSort implementation:
/* Bubble sort the given linked list */
void bubbleSort(Node *start, bool greaterThan(void* a, void* b))
{
int swapped, i;
Node* ptr1;
Node* lptr = NULL;
/* Checking for empty list */
if (start == NULL)
return;
do
{
swapped = 0;
ptr1 = start;
while (ptr1->next != lptr)
{
if (greaterThan(ptr1->item, ptr1->next->item))
{
swap(ptr1, ptr1->next);
swapped = 1;
}
ptr1 = ptr1->next;
}
lptr = ptr1;
}
while (swapped);
}
/* function to swap data of two nodes a and b*/
void swap(Node *a, Node *b)
{
void* temp = a->item;
a->item = b->item;
b->item = temp;
}
The first parameter of qsort requires a pointer to the array ...
How could I pass the pointer in this case?
typedef struct apData {
char ssid[32];
sint8 rssi;
AUTH_MODE authmode;
char bssid[18];
int32_t channel;
uint8 is_hidden;
} AP;
//BSSs SCANNED
typedef struct {
bool scanInProgress = NOT_SCANNING;
AP **apData;
int numAPs;
} Scan;
static Scan scanAPs;
...
The problem is here in passing the first parameter ...
I don't understand why I'm getting trash in the compareRSSI() function
qsort(scanAPs.apData, scanAPs.numAPs, sizeof(struct apData), compareRSSI);
...
int compareRSSI(const void *bss1, const void *bss2) {
int firstAP = ((struct apData *)bss1)->rssi;
int secondAP = ((struct apData *)bss2)->rssi;
return (secondAP - firstAP);
}```
You're passing to qsort a pointer to an array of pointers (apData is of type AP**), but you're saying that each element of the array is sizeof(struct apData) (as if it were an array of structures). So which is it?
You didn't show how you assigned scanAPs.apData a value, and you didn't show where you allocated storage for the elements of the array to be sorted. So, unfortunately, it's unclear if you intended to be sorting an array of pointers or if you intended to have an array of apData structures.
If the type declaration is correct and you have an array of pointers...
Since the type of apData is AP **, then you would have had an array of pointers to structures somewhere. In which case your sort call should have looked like:
qsort(scanAPs.apData, scanAPs.numAPs, sizeof(struct apData*), compareRSSI);
Note that the sizeof indicates that each element of the array is a pointer.
If the type declaration is wrong and you have an array of structures...
If it's the type that is wrong, then you need to change the type of apData to just AP*, and set it equal to the pointer to the first structure in the array. You'll need to assign an appropriate value somewhere and verify that you allocated storage for the array correctly too.
Do not use a C-style cast when assigning apData a value because the compiler will ensure that you have the right type.
Here's, My solution! these guys helped me a lot.
link!
qsort(scanAPs.apData, scanAPs.numAPs, sizeof(struct apData*), compareRSSI);
...
int compareRSSI(const void *bss1, const void *bss2) {
struct apData **firstAP = (struct apData **)bss1;
struct apData **secondAP = (struct apData **)bss2;
return ((*secondAP)->rssi - (*firstAP)->rssi);
}
I have
the struct:
typedef struct Rental {
int nDays;
float kmsDriven;
char carLicensePlate[LICENSE_PLATE_LENGTH+1];
char *clientName;
char chargingCategory;
} Rental;
Different -Rental type- structs are stored and accessed via a dynamically allocated array of pointers (here is a part of the project):
int main (){
Rental *rentals;
int max_num;
printf("Give a number of rentals you would like to store and manage: ");
scanf("%d", &max_num);
rentals=(Rentals *)malloc(max_num * (sizeof(Rental)))
This is what I have thought of so far but I can't understand it completely...so:
I'm having trouble understanding how *rentals can be an array. I mean shouldn't I declare it at least this way: Rental *rentals[];? I know that if I compile the above code I will see an error...but why?
I've read numerous posts here in Stack Overflow about doing this with double pointers (Rental **rentals;) but the code other people have posted is often very hard for me to read (I don't know all the functions etc. etc.)
Let's say I have the object rentals[0] which will be a pointer towards rentals. If I wanted to pass the struct to a function, should I write:
variable=function(*arguments*... , Rental *rentals[0]);?
rentals is a pointer, not an array, but it is a pointer to the first (zeroth) element of a block of max_num structures, so it can be treated as an array in that you can use rentals[n] to refer to the nth element of the array.
This is not a question and hence it is unanswerable.
Let's say I have the object rentals[0] which will be a pointer towards rentals. If I wanted to pass the struct to a function, should I write: variable=function(*arguments*... , Rental *rentals[0]);?
rentals[0] is not a pointer; it is a struct Rental or Rental.
If you want to pass the structure to the function, you write:
variable = function(…args…, rentals[0]);
If you want to pass a pointer to the structure to the function, you write:
variable = function(…args…, &rentals[0]);
or:
variable = function(…args…, rentals);
These pass the same address to the function.
You should be error checking the call to scanf() to make sure you got a number, and you should error check the number you got (it should be strictly positive, not zero or negative), and you should error check the value returned by malloc().
When you declare an array (for example char buffer[10]; the variable is actually pointing to that array. Pointers and arrays are very close together. In fact when you have a pointer where you store an array of data (just like your case with malloc) you can do something like pointer[0] and pointer[1] to get the correct element.
With a pointer in order to access an element you'd normally use *(pointer +1) to get the element on position 1, this is exactly the same as pointer[1].
When you want to pass a struct in an array, you can either give it by value like this:
void function(struct mystruct var)
{
//...
}
int main()
{
struct mystruct var;
function(var);
}
Or by reference (passing the address instead of the data - this is ideal if your structs are big in size) :
void function(struct mystruct *var)
{
//...
}
int main()
{
struct mystruct var;
function(&var);
}
By using an array, you can do it like this (still by reference):
void function(struct mystruct *var)
{
//...
}
int main()
{
struct mystruct var[10];
function(&var[0]);
}
And using a pointer (to an array) :
void function(struct mystruct *var)
{
//...
}
int main()
{
struct mystruct *var;
var = malloc( sizeof(struct mystruct) *10 );
//This will pass the address of the whole array (from position 0)
function(&var);
//This will pass the address of the selected element
function(&var[0]);
}
As you can see, declaring an array or a pointer is almost the same, expect that you have to initialize the pointer-array yourself (with malloc) and as with anything created with malloc you have to free it yourself too.
I am working with a function that modifies my array of structs called match by reallocating match and making it one struct bigger:
match = realloc(match, (sizeof(mStruct)*num_matches+1));
The struct prototype is as follows:
typedef struct{
char **names;
int score;
int diff;
} mStruct;
The problem is once I allocate memory inside the struct for an array of char pointers for their respective char arrays, the char pointers are never returned to the calling function since i'm returning type mStruct.
return match;
The rest of the statically declared variables are returned since they don't need special pointers to them. How would I go about returning the char pointers?
My the called functions parameters are as follows:
mStruct* trigger(pStruct *mArr, pStruct *wArr, mStruct *match)
The calling function looks like this
match = trigger(mArr, wArr, match);
Often stacks in C are dependent upon datatype used to declare them. For example,
int arr[5]; //creates an integer array of size 5 for stack use
char arr[5]; //creates a character array of size 5 for stack use
are both limited to holding integer and character datatypes respectively and presumes that the programmer knows what data is generated during the runtime. What if I want a stack which can hold any datatype?
I initially thought of implementing it as a union, but the approach is not only difficult but also flawed. Any other suggestions?
I would use a structure like this:
struct THolder
{
int dataType; // this is a value representing the type
void *val; // this is the value
};
Then use an array of THolder to store your values.
This is really just a variant of Pablo Santa Cruz' answer, but I think it looks neater:
typedef enum { integer, real, other } type_t;
typedef struct {
type_t type;
union {
int normal_int; /* valid when type == integer */
double large_float; /* valid when type == real */
void * other; /* valid when type == other */
} content;
} stack_data_t;
You still need to use some way to explicitly set the type of data stored in each element, there is no easy way around that.
You could look into preprocessor magic relying on the compiler-dependent typeof keyword to do that automagically, but that will probably not do anything but ruin the portability.
Some people have suggested a void* member. In addition to that solution I'd like to offer an alternative (assuming your stack is a linked list of heap-allocated structures):
struct stack_node
{
struct stack_node *next;
char data[];
};
The data[] is a C99 construct. data must be the last member; this takes advantage of the fact that we can stuff arbitrary quantities after the address of the struct. If you're using non-C99 compiler you might have to do some sketchy trick like declare it as data[0].
Then you can do something like this:
struct stack_node*
allocate_stack_node(size_t extra_size)
{
return malloc(sizeof(struct stack_node) + extra_size);
}
/* In some other function... */
struct stack_node *ptr = allocate_stack_node(sizeof(int));
int *p = (int*)ptr->data;
If this looks ugly and hacky, it is... But the advantage here is that you still get the generic goodness without introducing more indirection (thus slightly quicker access times for ptr->data than if it were void* pointing to a different location from the structure.)
Update: I'd also like to point out that the code sample I give may have problems if your machine happens to have different alignment requirements for int than char. This is meant as an illustrative example; YMMV.
You could use macros and a "container" type to reduce "type" from being per-element, to whole-container. (C99 code below)
#define GENERIC_STACK(name, type, typeid, elements) \
struct name##_stack { \
unsigned int TypeID; \
type Data[elements]; \
} name = { .TypeID = typeid }
Of course, your "TypeID" would have to allow every possible agreed-upon type you expect; might be a problem if you intend to use whole structs or other user-defined types.
I realize having a uniquely named struct type for every variable is odd and probably not useful... oops.
I created an library that works for any data type:
List new_list(int,int);
creates new list eg:
List list=new_list(TYPE_INT,sizeof(int));
//This will create an list of integers
Error append(List*,void*);
appends an element to the list. *Append accpts two pointers as an argument, if you want to store pointer to the list don't pass the pointer by pointer
eg:
//using the int list from above
int a=5;
Error err;
err=append(&list,&a)
//for an list of pointers
List listptr=new_list(TYPE_CUSTOM,sizeof(int*));
int num=7;
int *ptr=#
append(&listptr,ptr);
//for list of structs
struct Foo
{
int num;
float *ptr;
};
List list=new_list(TYPE_CUSTOM,sizeof(struct Foo));
struct Foo x;
x.num=9;
x.ptr=NULL;
append(&list,&x);
Error get(List*,int);
Gets data at index specified. When called list's current poiter will point to the data.
eg:
List list=new_list(TYPE_INT,sizeof(int));
int i;
for(i=1;i<=10;i++)
append(&list,&i);
//This will print the element at index 2
get(&list,2);
printf("%d",*(int*)list.current);
Error pop(List*,int);
Pops and element from the specified index
eg:
List list=new_list(TYPE_INT,sizeof(int));
int i;
for(i=1;i<=10;i++)
append(&list,&i);
//element in the index 2 will be deleted,
//the current pointer will point to a location that has a copy of the data
pop(&list,2);
printf("%d",*(int*)list.current);
//To use the list as stack, pop at index list.len-1
pop(&list,list.len-1);
//To use the list as queue, pop at index 0
pop(&list,0);
Error merge(List ,List);
Merges two list of same type. If types are different will return a error message in the Error object it returns;
eg:
//Merge two elements of type int
//List 2 will come after list 1
Error err;
err=merge(&list1,&list2);
Iterator get_iterator(List*);
Get an iterator to an list. when initialized will have a pointer to the first element of the list.
eg:
Iterator ite=get_iterator(&list);
Error next(Iterator*);
Get the next element of the list.
eg:
//How to iterate an list of integers
Iterator itr;
for(itr=get_iterator(&list); ite.content!=NULL; next(ite))
printf("%d",*(int*)ite.content);
https://github.com/malayh/C-List