bsearch() - Finding a string in an array of structs - c

I have a struct that looks like this:
typedef struct dictionary_t{
char word[30];
int foo;
int bar;
} dictionary_t;
Which forms an ordered array:
dictionary_t dictionary[100];
I would like to search this array for a string using bsearch() and get a pointer to the struct. So far this has worked:
dictionary_t* result;
char target[30] = "target";
result = bsearch(&target, dictionary, dict_length, sizeof(dictionary_t), (int(*)(const void*,const void*)) strcmp);
However this is a bit of a hack and only works because the string happens to be the first member of the struct. What would be a better way to find a string within an array of structs and return a pointer to the struct?

You should implement your own comparator function and pass it in. The most important (non-trivial) thing to keep in mind here is that according to the standard,
The implementation shall ensure that the first argument is always a pointer to the key.
This means that you can write a comparator that compares a string such as target and a dictionary_t object. Here is a simple function that compares your stucts to a string:
int compare_string_to_dict(const void *s, const void *d) {
return strncmp(s, ((const dictionary_t *)d)->word, sizeof(((dictionary_t *)0)->word));
}
You would then pass it by name as a normal function pointer to bsearch:
result = bsearch(target, dictionary, dict_length, sizeof(dictionary_t), compare_string_to_dict);
Note that target does not need to have its address passed in since it is no longer mocking a struct.
In case you are wondering, sizeof(((dictionary_t *)0)->word) is an idiomatic way of getting the size of word in dictionary_t. You could also do sizeof(dictionary[0].word) or define a constant equal to 30. It comes from here.

Related

how to call a function by pointer in C

I have been going through the Atmel library USB for AT91SAM7 and there is something I don’t understand. Endpoint is a structure defined as follows:
typedef struct {
volatile unsigned char state;
volatile unsigned char bank;
volatile unsigned short size;
Transfer transfer; //thus Endpoint contains an instance of "Transfer"
} Endpoint
point;
And Transfer itself is a structure as follows:
typedef struct {
char *pData;
volatile int buffered;
volatile int transferred;
volatile int remaining;
volatile TransferCallback fCallback;
void *pArgument;
} Transfer;
And TransferCallback is a function with the following prototype:
typedef void (*TransferCallback)(void *pArg, unsigned char status, unsigned int transferred, unsigned int remaining);
also two pointers have been defined as the following:
Endpoint *pEndpoint = &(endpoints[bEndpoint]);
Transfer *pTransfer = &(pEndpoint->transfer);
I want to know why such a way to call the function TransferCallback is valid:
((TransferCallback) pTransfer->fCallback) (followed by the required arguments passed )
But this is not valid:
((TransferCallback)pEndpoint->transfer->fCallback)?
how could I directly call TransferCallback without using a pointer such as pTransfer in between?
I tried a number of combinations but none worked.
Note that Endpoint does not have a pointer to Transfer member (*Transfer), but a Transfer member. In machine terms, rather than a single word of memory within each Endpoint being used as a pointer to a Transfer, all the fields of the Transfer member are stored directly inside the memory allocated for the Endpoint.
To cut to the chase, what you need is:
((TransferCallback)pEndpoint->transfer.fCallback)
Regarding the title to the OP: how to call a function by pointer in C
+1 to Alex's answer of your question about How, but there is another point that can be made in the interest of knowing Why choose a function pointer over just providing the normal function name in the first place; Function pointers are especially useful in C* (see *) when you have a collection of functions that are similar in that they contain the same argument list, but have different outputs. You can define an array of function pointers, making it easier, for example, to call the functions in that family from a switch, or a loop, or when creating a series of threads in a pool that include similar worker functions as arguments. Calling an array makes it as simple as changing the index of the pointer to get the specific functionality you need for each unique case.
As a simple example, the two string functions strcat() and strcpy() have the argument list: (char *, const char *), therefore, may be assigned to an array of function pointers. First create the function pointer array:
char * (*pStr[2])( char *a, const char *b);` //array of function pointers pStr[]
Then, make the assignements of strcat and strcpy to the array:
void someFunc(void)
{
pStr[0] = strcat; //assign strcat to pointer [0]
pStr[1] = strcpy; //assign strcpy to pointer [1]
}
Now, strcat() or strcpy() can be called as:
int main(void)
{
char a[100]="kjdhlfjgls";
char b[100]="kjdhlfjgls";
someFunc();//define function pointers
pStr[0](a, "aaaaaaaa"); //strcat
pStr[1](b, "aaaaaaaa"); //strcpy
return 0;
}
Example output:
This is just a simple example. It does not explore the full extent of usefulness function pointers can provide, but illustrates another reason why functions pointers may be preferred in some situations.
* This illustration is targeted only to C, as opposed to C++, where qualities of inheritance and polymorphism inherent to that language would make this suggestion unnecessary.

C Function implementation - with Pointer vs without Pointer

I've just started to work with C, and never had to deal with pointers in previous languages I used, so I was wondering what method is better if just modifying a string.
pointerstring vs normal.
Also if you want to provide more information about when to use pointers that would be great. I was shocked when I found out that the function "normal" would even modify the string passed, and update in the main function without a return value.
#include <stdio.h>
void pointerstring(char *s);
void normal(char s[]);
int main() {
char string[20];
pointerstring(string);
printf("\nPointer: %s\n",string);
normal(string);
printf("Normal: %s\n",string);
}
void pointerstring(char *s) {
sprintf(s,"Hello");
}
void normal(char s[]) {
sprintf(s,"World");
}
Output:
Pointer: Hello
Normal: World
In a function declaration, char [] and char * are equivalent. Function parameters with outer-level array type are transformed to the equivalent pointer type; this affects calling code and the function body itself.
Because of this, it's better to use the char * syntax as otherwise you could be confused and attempt e.g. to take the sizeof of an outer-level fixed-length array type parameter:
void foo(char s[10]) {
printf("%z\n", sizeof(s)); // prints 4 (or 8), not 10
}
When you pass a parameter declared as a pointer to a function (and the pointer parameter is not declared const), you are explicitly giving the function permission to modify the object or array the pointer points to.
One of the problems in C is that arrays are second-class citizens. In almost all useful circumstances, among them when passing them to a function, arrays decay to pointers (thereby losing their size information).
Therefore, it makes no difference whether you take an array as T* arg or T arg[] — the latter is a mere synonym for the former. Both are pointers to the first character of the string variable defined in main(), so both have access to the original data and can modify it.
Note: C always passes arguments per copy. This is also true in this case. However, when you pass a pointer (or an array decaying to a pointer), what is copied is the address, so that the object referred to is accessible through two different copies of its address.
With pointer Vs Without pointer
1) We can directly pass a local variable reference(address) to the new function to process and update the values, instead of sending the values to the function and returning the values from the function.
With pointers
...
int a = 10;
func(&a);
...
void func(int *x);
{
//do something with the value *x(10)
*x = 5;
}
Without pointers
...
int a = 10;
a = func(a);
...
int func(int x);
{
//do something with the value x(10)
x = 5;
return x;
}
2) Global or static variable has life time scope and local variable has scope only to a function. If we want to create a user defined scope variable means pointer is requried. That means if we want to create a variable which should have scope in some n number of functions means, create a dynamic memory for that variable in first function and pass it to all the function, finally free the memory in nth function.
3) If we want to keep member function also in sturucture along with member variables then we can go for function pointers.
struct data;
struct data
{
int no1, no2, ans;
void (*pfAdd)(struct data*);
void (*pfSub)(struct data*);
void (*pfMul)(struct data*);
void (*pfDiv)(struct data*);
};
void add(struct data* x)
{
x.ans = x.no1, x.no2;
}
...
struct data a;
a.no1 = 10;
a.no1 = 5;
a.pfAdd = add;
...
a.pfAdd(&a);
printf("Addition is %d\n", a.ans);
...
4) Consider a structure data which size s is very big. If we want to send a variable of this structure to another function better to send as reference. Because this will reduce the activation record(in stack) size created for the new function.
With Pointers - It will requires only 4bytes (in 32 bit m/c) or 8 bytes (in 64 bit m/c) in activation record(in stack) of function func
...
struct data a;
func(&a);
...
Without Pointers - It will requires s bytes in activation record(in stack) of function func. Conside the s is sizeof(struct data) which is very big value.
...
struct data a;
func(a);
...
5) We can change a value of a constant variable with pointers.
...
const int a = 10;
int *p = NULL;
p = (int *)&a;
*p = 5;
printf("%d", a); //This will print 5
...
in addition to the other answers, my comment about "string"-manipulating functions (string = zero terminated char array): always return the string parameter as a return value.
So you can use the function procedural or functional, like in printf("Dear %s, ", normal(buf));

Trying to understand function pointers in C

I am trying to understand function pointers and am stuggling. I have seen the sorting example in K&R and a few other similar examples. My main problem is with what the computer is actually doing. I created a very simple program to try to see the basics. Please see the following:
#include <stdio.h>
int func0(int*,int*);
int func1(int*,int*);
int main(){
int i = 1;
myfunc(34,23,(int(*)(void*,void*))(i==1?func0:func1));//34 and 23 are arbitrary inputs
}
void myfunc(int x, int y, int(*somefunc)(void *, void *)){
int *xx =&x;
int *yy=&y;
printf("%i",somefunc(xx,yy));
}
int func0(int *x, int *y){
return (*x)*(*y);
}
int func1(int *x, int *y){
return *x+*y;
}
The program either multiplies or adds two numbers depending on some variable (i in the main function - should probably be an argument in the main). fun0 multiplies two ints and func1 adds them.
I know that this example is simple but how is passing a function pointer preferrable to putting a conditional inside the function myfunc?
i.e. in myfunc have the following:
if(i == 1)printf("%i",func0(xx,yy));
else printf("%i",func1(xx,yy));
If I did this the result would be the same but without the use of function pointers.
Your understanding of how function pointers work is just fine. What you're not seeing is how a software system will benefit from using function pointers. They become important when working with components that are not aware of the others.
qsort() is a good example. qsort will let you sort any array and is not actually aware of what makes up the array. So if you have an array of structs, or more likely pointers to structs, you would have to provide a function that could compare the structs.
struct foo {
char * name;
int magnitude;
int something;
};
int cmp_foo(const void *_p1, const void *_p2)
{
p1 = (struct foo*)_p1;
p2 = (struct foo*)_p2;
return p1->magnitude - p2->magnitude;
}
struct foo ** foos;
// init 10 foo structures...
qsort(foos, 10, sizeof(foo *), cmp_foo);
Then the foos array will be sorted based on the magnitude field.
As you can see, this allows you to use qsort for any type -- you only have to provide the comparison function.
Another common usage of function pointers are callbacks, for example in GUI programming. If you want a function to be called when a button is clicked, you would provide a function pointer to the GUI library when setting up the button.
how is passing a function pointer preferrable to putting a conditional inside the function myfunc
Sometimes it is impossible to put a condition there: for example, if you are writing a sorting algorithm, and you do not know what you are sorting ahead of time, you simply cannot put a conditional; function pointer lets you "plug in" a piece of computation into the main algorithm without jumping through hoops.
As far as how the mechanism works, the idea is simple: all your compiled code is located in the program memory, and the CPU executes it starting at a certain address. There are instructions to make CPU jump between addresses, remember the current address and jump, recall the address of a prior jump and go back to it, and so on. When you call a function, one of the things the CPU needs to know is its address in the program memory. The name of the function represents that address. You can supply that address directly, or you can assign it to a pointer for indirect access. This is similar to accessing values through a pointer, except in this case you access the code indirectly, instead of accessing the data.
First of all, you can never typecast a function pointer into a function pointer of a different type. That is undefined behavior in C (C11 6.5.2.2).
A very important advise when dealing with function pointers is to always use typedefs.
So, your code could/should be rewritten as:
typedef int (*func_t)(int*, int*);
int func0(int*,int*);
int func1(int*,int*);
int main(){
int i = 1;
myfunc(34,23, (i==1?func0:func1)); //34 and 23 are arbitrary inputs
}
void myfunc(int x, int y, func_t func){
To answer the question, you want to use function pointers as parameters when you don't know the nature of the function. This is common when writing generic algorithms.
Take the standard C function bsearch() as an example:
void *bsearch (const void *key,
const void *base,
size_t nmemb,
size_t size,
int (*compar)(const void *, const void *));
);
This is a generic binary search algorithm, searching through any form of one-dimensional arrray, containing unknown types of data, such as user-defined types. Here, the "compar" function is comparing two objects of unknown nature for equality, returning a number to indicate this.
"The function shall return an integer less than, equal to, or greater than zero if the key object is considered, respectively, to be less than, to match, or to be greater than the array element."
The function is written by the caller, who knows the nature of the data. In computer science, this is called a "function object" or sometimes "functor". It is commonly encountered in object-oriented design.
An example (pseudo code):
typedef struct // some user-defined type
{
int* ptr;
int x;
int y;
} Something_t;
int compare_Something_t (const void* p1, const void* p2)
{
const Something_t* s1 = (const Something_t*)p1;
const Something_t* s2 = (const Something_t*)p2;
return s1->y - s2->y; // some user-defined comparison relevant to the object
}
...
Something_t search_key = { ... };
Something_t array[] = { ... };
Something_t* result;
result = bsearch(&search_key,
array,
sizeof(array) / sizeof(Something_t), // number of objects
sizeof(Something_t), // size of one object
compare_Something_t // function object
);

C existing pointer to fixed-size array

Let's say that any C function has a pointer already declared, but not assigned any value yet. We will int for our examples.
int *ptr;
The goal of the function is not to assign ptr any dynamic memory on the heap, so no malloc call. Instead, we want to have it point to an array of fixed size n. I know I could accomplish this like so:
int arr[n];
ptr = arr;
However, the code could get very messy and hard to read if we need to do this many times in a function, ie, a struct of many pointer fields all need to point to an array of fixed length. Is there a better way to accomplish this in one line? I was thinking of something similar to below, but it looks too ambiguous and uncompilable:
int *ptr;
// Many other things happen in between...
ptr[n];
***EDIT***
Here, the below additional information may help guide some more answers (not saying that the current answers are not fine). In my use case, the pointers are declared in a struct and, in a function, I am assigning the pointers to an array. I want to know if there is a simpler way to accomplish this than in the below code (all pointers to point to fixed-length array):
struct foo {
int* a;
short* b;
char* c;
...
};
void func(void) {
struct foo f;
int n = ...;
int tempArr1[n];
f.a = tempArr1;
short tempArr2[n];
f.b = tempArr2;
char tempArr3[n];
f.c = tempArr3;
...
}
You cannot declare an array and assign it to an existing pointer in a single declaration. However, you can assign an array pointer to a newly declared pointer, like this:
int arr[n], *ptr = arr;
If you insist on staying within a single line, you could use an ugly macro, like this:
#define DECL_ASSIGN_INT_ARRAY(name,size,pointer) int name[(size)]; pointer = name;
The clarity of this one-liner is far lower than that of a two-line version from your post, so I would keep your initial version.
EDIT (in response to the edit of the question)
Another option is to create an unused pointer variable in a declaration, and assign your pointer in an initializer, like this:
void func(void) {
struct foo f;
int n = ...;
int tempArr1[n], *tempPtr1 = f.a = tempArr1;
short tempArr2[n], *tempPtr2 = f.b = tempArr2;
char tempArr3[n], *tempPtr3 = f.c = tempArr3;
...
}
This seems like a clear case where you're in need of some refactoring. Take the similar statements, extract them into a new function (by passing a reference to the struct and the data you want the struct fields to point to) and give this new function a meaningful name.
This is probably more maintainable and readable than some fancy pointer arithmetic shortcut that you'll forget about in a few weeks or months.
The difference between ptr and arr in you example is you can change ptr's value. So I guess you want to move ptr through the array.
So how about this:
int arr[n], id=0;
And you change the value of id and use arr+id as ptr.
I guess the way to do this is to use a macro. Something like (untested)
#define autoptr(name,size) int Arrayname[size]; name = Arrayname;
I'm not clear why this is helping I think it might "look ugly" but will be easier to maintain without the macro. In general, hiding what you are actually doing is a bad thing.

qsort not sorting structure correctly

I'm trying to sort a structure I've created via qSort however it seems to be be doing what I expect it to.
This is my compare function
int compare(const void *a, const void *b) {
const INPUT *p1 = a;
const INPUT *p2 = b;
return ((p1->startTime) - (p2->startTime));
}
Where INPUT is my structure and startTime is an int within it.
I call qsort by this
qsort(*global,fileNumber,sizeof(global)/fileNumber,compare);
Where global is the variable name of INPUT, fileNumber is how many entries are within the global variable.
From the printf statements I've written it seems to do nothing.
I've initialized at the beginning of my code global like this
INPUT *global[4];
Any ideas on what I've done wrong?
Thanks
As you send *global to qsort, I can imagine that you defined global as:
INPUT **global;
Thus, when you give sizeof(global)/fileNumber as third argument to qsort, sizeof is probably 4 (or 8 on a 64 bits systems). Then this argument is propably zero.
Hence qsort does nothing on a zero element array, and never calls compare.
You global array is an array of pointers, not an array of INPUT structs. So your compare function should look something like:
int compare(const void *a, const void *b) {
const INPUT **p1 = a;
const INPUT **p2 = b;
return (((*p1)->startTime) - ((*p2)->startTime));
}
And your call to qsort():
qsort(global,fileNumber,sizeof(global)/fileNumber,compare);
Of course, all this assumes that you are really using global as an array of pointers rather than a pointer to an array of INPUT structs.

Resources