This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how to use array of function pointers?
I am wondering how one can declare in C a dynamic list of function pointers ? Using a pointer to function pointer ?
A pointer to a function pointer, with which you can use to point to a block of dynamically allocated memory. Let's say the function type is void (int):
void (*(*))(int) // Bare type
void (*(*f))(int) // Variable
Or you may want an array to function pointers, in which case:
void (*[10])(int) // Bare type
void (*af[10])(int) // Variable
You can change the parameter and the return type of the functions.
An array of function pointers can be used as a map from number to function to be executed. It is one way to do emulation - for example, after you have obtained the OP code from the instruction, you can execute the operation by using the array of pointer. (This is one way to do so, but I'm not sure whether it is actually done in emulation code).
For a dynamic list, you can use a basic linked list:
struct list {
int (*func)(int, float, double);
struct list *next;
}
Or an array of function pointers which is resized as necessary.
Yes you can have an array of function pointers.
This might be useful, for instance for collecting a set of callback functions for a specific event.
As an example, consider implementing addEventListener to DOM elements in a browser, where any DOM element can have multiple click events. A simple data structure might be:
void (*clickHandlers[MAX_EVENT_HANDLERS])(EventData arg);
For a dynamic list then allocate a buffer of function pointers using malloc, and realloc as you need more space:
void (**clickHandlers)(EventData arg);
Related
This question already has answers here:
Can we have a struct element of type Variable length array? [duplicate]
(5 answers)
Closed 2 years ago.
I would like to define array size inside a structure by using a parameter of this structure. Does C permit to do something like this ?
struct queue {
int head;
int top;
int size;
struct action action[size];
};
No you can't. Since action is not a dynamic variable, the compiler needs to know at compile time how much space it needs for action. size was not even initialized. Anyway, you could see this just by trying to compile.
The size is not known at the time of defining the struct. Therefore it is impossible for the compiler to understand how large the result will be. Typically, you would first allocate memory for the struct, and have a struct action *action; member. After initializing the struct, you use instance->action = calloc(instance->size, sizeof *instance->action) to allocate memory for the array.
#define BUFF_SIZE 100000
unsigned char buffer[BUFF_SIZE];
void myfunc(unsigned char[],int,int);
void myfuncinfunc(unsigned char[],int,int);
int main()
{
int a = 10, b = 10;
myfunc(buffer,a,b);
}
void myfunc(unsigned char array[],int a,int b)
{
int m,n;
//blah blah
myfuncinfunc(array,m,n);
}
void myfuncinfunc(unsigned char array[],int a, int b)
{
//blah blah
}
I wish to know the following:
I have created a static array as seen above the 'main' function. Is this efficient? Would it be better if I used a point and malloc instead?
I know it doesn't use the stack, so when I pass the array into inner functions, would it create a copy of the whole array or just send the location of the first entry?
When working on 'array' in the function 'myfunc', am I working directly with the static defined array or some local copy?
Inside the function 'myfunc', when we pass the array into the function 'myfuncinfunc', would it again, send only the first location or a complete copy of the array into the stack?
Thanks for reading the question and would greatly appreciate any help! I'm new to C and trying to learn it off the internet.
I don't see how it would be more or less efficient than an array on the heap.
It decays into a pointer to the first entry.
Therefore it's not a local copy, it's the array itself.
Ditto.
By the way, if a and b are indexes within the array, consider using the size_t type for them (it's an unsigned int guaranteed big enough for indexing arrays).
I have created a static array as seen above the 'main' function. Is this efficient? Would it be better if I used a point and malloc instead?
Define "efficient". Statically allocated arrays are always faster than dynamic ones, because of the runtime overhead for allocation/deallocation.
In this case, you allocate a huge amount of 100k bytes, which might be very memory-inefficient.
In addition, your process might not have that much static memory available, depending on OS. On desktop systems, it is therefore considered best practice to allocate on the heap whenever you are using large amounts of data.
I know it doesn't use the stack, so when I pass the array into inner functions, would it create a copy of the whole array or just send the location of the first entry?
You can't pass arrays by value in C. So a pointer to the first element of the array will be saved on the stack and passed to the function.
When working on 'array' in the function 'myfunc', am I working directly with the static defined array or some local copy?
Directly on the static array. Again, you can't pass arrays by value.
Inside the function 'myfunc', when we pass the array into the function 'myfuncinfunc', would it again, send only the first location or a complete copy of the array into the stack?
A pointer to the first element.
This question already has answers here:
Declaring a C function to return an array
(5 answers)
Closed 9 years ago.
I have just started my back-to-the-roots project; learning C. I'll be honest, abstraction is nice when you need to plow out a desktop/server application, but with C, things get personal. Which is nice, for a change!
Now to the point; I'm reading into using arrays with functions (Programming in C, Stephen G. Kochan.) I have learnt that when passing an function as a parameter the compiler will always see the reference as a pointer, like so:
void foo (char *array);
Take this, for example:
void foo (char *a)
{
a[0] = 'R'; // side effect
}
int main (void)
{
char a[] = "The quick brown fox jumps over the lazy dog!";
foo (a);
}
I haven't come by information on functions returning arrays or pointer to an array. The function rather changes the array in its parameter, thus causing side effects (as seen above).
Is it possible for a function to return a pointer to an array? Or is the above method just preferred?
Thanks in advance for those that can offer an explanation.
A function can return a pointer to the first element of an array, but it's more problematic, you either have to malloc the memory (like strdup) for the array or have a static array (like ctime).
malloc gives the problem of having to remember to free the memory (memory leaks), static means the array changes with each call, therefore passing an existing array is easier.
I am not sure I follow. Your function is of type void. Are you trying to modify the array by passing it as reference?
In C, if you return a pointer to the first element of the array, you effective return the entire array because C arrays are contiguous in the programs memory (may be not in physical memory). So when you return the pointer to the first element, you effectively tell your main function where the entire array is stored.
Why would you do this:
void f(Struct** struct)
{
...
}
If I wish to operate on a list of structs, is it not enough to pass in a Struct*? This way I can do struct++ to address the next struct or am I very confused here? :)
Wouldn't it only be useful if I want to rearrange the list of structs in some way? However if I'm just reading I don't see the point.
It depends on what your data structure looks like. Assuming that p is a null-terminated array of pointers to struct s, you can run through it using a loop like this:
void f(struct s **p)
{
while (*p != NULL) {
/* some stuff */
(*p)++;
}
}
Generally, use a pointer to a pointer is useful only if you attempt to modify the pointer itself.
If you want to modify the pointer in caller which was passed to this function, you'd typically do this.
Because, everything is passed by value in C, passing struct* will only pass the copy of the pointer and won't modify pointer in the caller. Why passing struct * is explained in this C-FAQ.
If you don't intend to modify the pointer in caller, it's not neccessary to pass struct **.
There are a number of uses for this kind of parameter...
One already mentioned, and quite common is to allow the caller to use the function to modify a pointer. The obvious case here would be when getting some blob of data...
void getData( void** pData, int* size )
{
*pData = getMyDataPointer();
*size = getMyDataSize();
}
Another option is that perhaps the extra level of indirection allows for the list to behave in some way? e.g. by using indices to refer to specific elements they can be allocated and reallocated without having the risk of dangling pointers.
Yet another option is that the list is very large and lives in fragmented memory, or is rapidly accessed so that the list is actually several smaller lists grouped together. This sort of technique can also be used to 'lazily' allocate huge arrays, e.g. providing an interface to an array of a billion elements, but then allocating chunks of 100k on demand as they are read/written with struct** pointing at the whole thing, and each struct* being either null or pointing to 100k structs...
To be honest the context is quite important... there are plenty of uses for also triple pointers as function parameters that follow similar reasoning. (e.g. combine the first thing i mention with the second, or the second with the third etc.)
You are correct, there is no reason to pass a pointer to pointer unless your function is intended to modify the pointer passed in. In case of accessing an array of structs, a single level of indirection is definitely sufficient.
The creator of the API probably thought that the argument list would be easier to memorize if the first argument of every function is the same.
I want to pass an array of arbitrary struct pointers and a comparison function to a generic sorting algorithm. Is this possible in C?
The goooeys of the structs would only be accessed within the comparison function, the sorting function would only need to call the comparison function and swap pointers, but I can't figure out how to declare it.
function sorter( struct arbitrary ** Array, int Length, int cmp(struct node * a, struct node * b))
{
for (int i=0; i<Length;i++){
if cmp(Array[i],Array[i+1]){
swap(Array[i],Array[i+1]
}
}
}
You can declare the function as:
void sorter(void** the_array, size_t array_length, int (*comparison_function)(void*, void*));
Inside of the comparison function, you will then need to cast the two pointers being compared to pointers to whatever struct type the comparison function compares.
Actually, this function already exists... it is called qsort. See some documentation here. It's also more efficient than your implementation, which is O(n^2).
Maybe you need to pass just void pointers?
function sorter(void ** Array, int Length, int cmp(void * a, void * b))
It's always possible in C simply because you can convert every pointer to a void*. But, if you want to be able to convert that back to a pointer to an arbitrary structure, you'll need some sort of type identification.
You could do that by using a function specific to the type (if the things you are comparing are the same), or encode the type into the structure somehow. This can be done by having an extra field in the structure or by changing the cmp() function itself to take a type identifier.
But you should be aware that C already has a qsort() function that's usually reasonably efficient (although there's nothing in the standard that dictates what algorithm it uses - it could use bubble sort and still be conforming). Unless you're implementing one for homework, or have a different algorithm in mind, tou should probably just use that.
Your algorithm, as it stands, looks like the inner loop of a bubble sort and, as such, won't actually sort correctly. Bubble sort consists of two nested loops and is generally only suitable for small data sets or those with specific characteristics (such as mostly sorted already).