As this is C, you cannot pass the pointer by reference without passing in a pointer to the pointer (e.g., void ** rather than void * to point to the pointer). You need to return the new pointer. What is happening:
f(a1);
Pushes the value of the pointer (NULL) as the stack parameter value for a. a picks up this value, and then reassigns itself a new value (the malloced address). As it was passed by value, nothing changes for a1.
If this were C++, you could achieve what you want by passing the pointer by reference:
void f(void *&a);
Answer from pickypg on Stack OverflowAs this is C, you cannot pass the pointer by reference without passing in a pointer to the pointer (e.g., void ** rather than void * to point to the pointer). You need to return the new pointer. What is happening:
f(a1);
Pushes the value of the pointer (NULL) as the stack parameter value for a. a picks up this value, and then reassigns itself a new value (the malloced address). As it was passed by value, nothing changes for a1.
If this were C++, you could achieve what you want by passing the pointer by reference:
void f(void *&a);
Passing a pointer to a1 to your function, you can't change where a1 points. The pointer is passed by value, so in f1 you're only changing a copy of the address held by a. If you want to change the pointer, i.e. allocate new memory for the pointer passed in, then you'll need to pass a pointer to a pointer:
void f1(void **a)
{
// ...
*a = malloc(sizeof(int));
// ...
Videos
As far as i understood void(*)() works in a similiar way void* works, but with function pointers, meaning you can cast any function pointer to it and back. Is this correct? However, i ran into a strange issue.
void foo(int i) {
}
void bar(char c) {
}
void test(void(*)()) {
}
int main() {
test(foo); //test(bar); compile error
}
I get an incompatible pointer type error if i try to pass a function with param char, but it works with param int, why would that be? Thanks!
I apologize for the formatting, writing from my phone.
Unfortunately you did not provide enough code to show it in your code. You will need to fill the blanks.
To call the passed compare function, you need to do the arithmetics on your own:
int sort(void *ptr, int N, int sizeof_element, f f)
{
uint8*p = ptr;
// ... Doing the sorting things...
//Assuming you want to compare element j and k in the array
int result = f( &p[j*sizeof_element], &p[k*sizeof_element] );
// ... Doing more sorting things
}
With your updated code I want to add, that you mustn't call comp_double directly in the sort function. That is what f is intented to be used for.
The error message you get is because you cannot do pointer arithmetics on a void* as void does not have a size. (Except with some GCC extensions)
How can I pass void pointer to function in C?
You already are, so that's not your problem.
I am writing about this line which is inside sort function:
comp_double((void *)(ptr + j), (void *)(ptr + j + 1))
OK, it's not passing void* you're having trouble with, but doing pointer arithmetic on it.
The reason is that there's no type associated with void*, so the compiler doesn't know how many bytes ptr+1 should be advanced. If you were using char *ptr, it would be one byte. For double* ptr it would be sizeof(double) bytes, etc.
Since we can't cast ptr to the correct type (it can be different on each call, which is what makes the function reusable), we have to do this pointer arithmetic manually instead:
char *base = (char *)ptr;
...
comp_double(base + j*sizeof_element, base + (j + 1)*sizeof_element);
Notes:
- the pointer argument can be implicitly cast back to
void*, there's no need to do it explicitly - any pointer
T*such thatsizeof(T)==1will work correctly:charis kind of traditional,uint8is also fine
No, you cannot pass function pointer as void *.
6.3.2.3 Pointers
- A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.
and
- A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.
Notice how there is no mention of possibility to mix object and function pointers. It may seem to work on some system, but it's undefined behaviour and not guaranteed to work.
However, you can create wrapper object and pass address of that:
struct wrapper {
my_custom_callback_t func;
};
struct wrapper my_wrapper = { my_custom_callback };
someAPIFunction( /*...*/, standard_callback, &my_wrapper);
Or just pass pointer to function pointer (function pointer variable is object type):
my_custom_callback_t func = my_custom_callback;
someAPIFunction( /*...*/, standard_callback, &func);
Most platforms will in fact allow you to pass a function pointer as a void *, but it's not theoretically allowed. Code might have different pointers to data. You also cannot pass a const-qualified address to a void *.
C uses pass-by-value for function argument passing. If you have to change the passed variable itself from inside the function, you need to have a pointer to the variable.
In your case, it should be a pointer to pointer.
Otherwise, after the call to f1(a1);, in f(), a is still NULL and dereferencing it invokes undefined behaviour. Segmentation fault is one of the side effects of UB.
That said,
Please see why not to cast the return value of
malloc()and family inC.you don't need
#include "malloc.h"to usemalloc(), rather use#include <stdlib.h>. It is declared instdlib.hheader file.
You need to modify the pointer, not the ponted to data. So you must pass a pointer to the pointer, like this
void f1(void **a)
{
int *b;
b = malloc(sizeof(*b));
printf("b address = %p \n", b);
if (b != NULL)
{
b[0] = 3;
printf("data = %d\n", *(int *) b);
}
*a = b;
}
The way you do it, the pointer inside f1 is a copy of the passed pointer, they both contain the same initial value NULL, the value you used in f() to initialize a1, but you alter the value of the local pointer only.
You then dereference a1 which is still NULL, and dereferencing a NULL pointer, causes undefined behavior. In your case the behavior is that a segmentation fault happens.
void * is a pointer type. You're not passing pointers, you're passing values, so that's not going to compile. It accidentally "works" for int because pointers themselves are represented as integers by most C compilers.
If you pass pointers to int, float, and double instead of the int, float, and double themselves, you will avoid that compiler error. You'd also need to change int_add and friends to take pointers, and you'd have to make sure you dereferenced the pointers before using them. You'll also have to return pointers, which means you'll have to malloc some memory on the heap, because the stack memory assigned to your local variables will be invalid once your function exits. You'll then have to free it all later... in the end, this is going to result in something considerably more complicated than the problem it appears you are trying to solve.
I have to ask why you are trying to do this? C is really not the best language for this type of pattern. I'd suggest just calling the int_add, float_add, etc. functions directly instead of trying to abstract them in this way.
So as per @charles-srstka suggestion I rewrote the code and then it worked as I wanted
#include<stdio.h>
#include<stdlib.h>
int* int_add(int *x, int *y) {
int *c = (int *)malloc(sizeof(int));
*c = *(int*)x + *(int*)y;
return c;
}
float* float_add(float *x, float *y) {
float *c = (float*)malloc(sizeof(float));
*c = *(float*)x + *(float*)y;
return c;
}
void* do_operation(void* (*op)(void*, void*), void* x, void* y) {
return op(x, y);
}
void main(void) {
int a = 1;
int b = 2;
int *c;
c = do_operation(int_add, &a, &b);
printf("%d\n",*c);
free(c);
float x = 1.1;
float y = 2.2;
float *z;
z = do_operation(float_add, &x, &y);
printf("%f\n",*z);
free(z);
}
You can simply create a function (func2) that takes a function pointer to your desired function that you want called and another paramter that takes a pointer to your string. Then in func2 call the passed in function pointer with the str argument.
#include <stdio.h>
void func1(const char *str)
{
puts(str);
}
void func2(void (*fp)(const char *), const char *str)
{
fp(str);
}
int main(void)
{
const char *str = "Hello world.";
func2(func1, str);
return 0;
}
First of all: A function pointer refers to a function only. Parameters come into the game when the function is called, either directly or via a function pointer.
So if you want to achieve what you have in mind, that is binding a (set of) parameters to a specific function varaible you need to use a wrapper function:
int func1(char * pc)
{
int i;
/* assigne somehting to "i" and use "pc" */
return i;
}
int func1_abcd(void)
{
return func1("abcd")
}
int func1_xyz(void)
{
return func1("xyz")
}
typedef int (*pfunc1_wrapper_t)(void);
int func2(pfunc1_wrapper_t pfunc1_wrapper)
{
return pfunc1_wrapper();
}
int main(int argc, char ** argv)
{
pfunc1_wrapper_t pfunc1_wrapper = NULL;
int i = 0;
pfunc1_wrapper = func1_abcd;
i = func2(pfunc1_wrapper);
pfunc1_wrapper = func1_xyz;
i = func2(pfunc1_wrapper);
...
return 0;
}
You need to cast void* pointer to the function pointer first:
#include <stdio.h>
typedef struct {
void* fn;
void* param;
} event;
void print()
{
printf("Hello\n");
}
int main()
{
event e;
e.fn = print;
((void(*)())e.fn)();
return 0;
}
Of course, if this is really what you want. If you want your struct to contain pointer to the function, instead of void* pointer, use the proper type at the declaration:
typedef struct {
void (*fn)();
void* param;
} event;
Here you have fn declared as a pointer to the void function, and the param as void* pointer.
event is a type, not an object or expression. You can't access a member of a structure type, only of an object of a structure type.
So given:
typedef struct {
void* fn;
void* param;
} event;
you need to have an object of type event, and you need to assign values to its members.
In your question, you use fn as a member name, but then you refer to something called function. I'll assume here that they're supposed to be the same thing, and that fn is supposed to point to some function.
You can't portably store a function pointer in a void*. On many, probably most, implementations you can get away with it, but it's not guaranteed by the language. (There are systems were function pointers are bigger than data pointers, and converting a function pointer to void* loses information.) On the other hand, all pointer-to-function types are convertible to each other, and a round-trip conversion is guaranteed to give you the original pointer value.
I'll assume (I'm making a lot of assumptions here because you didn't provide a lot of information) that you want fn to point to a function that takes a void* argument and doesn't return a result; then making param a void* makes sense. For consistency with that assumption, we can alter your type definition:
typedef struct {
void (*fn)(void*);
void *param;
} event;
(The void (*fn)(void*); syntax is not entirely obvious. I used cdecl to construct it.)
Now you can define an object of type event:
event e = { some_func, NULL };
You have to have defined some_func somewhere, as
void some_func(void *param { /* ... */ }
or equivalent. Now you can call that function indirectly through the event object e:
e.fn(e.param);
Or, if it's more convenient to have a pointer to an event:
event *ptr = malloc(sizeof *ptr);
if (event == NULL) {
/* error handling here */
}
ptr->fn = some_func;
ptr->param = NULL;
and you can use indirection both on the pointer-to-event and on the function pointer contained in the event object it points to:
ptr->fn(ptr->param);
Depending on what you're trying to accomplish, you might want fn to be able to point to functions of different types. If you do that, you must convert (with an explicit cast) e.fn or ptr->fn to the actual type of the function it points to before making a call through it. You can't blindly mix function pointers of different types; if you do, the result is either a compile-time error or run-time undefined behavior. You can use void (*)(void) (pointer to function with no parameters and returning no result) as a "generic" function pointer type, but unlike with void* any conversions to the type you need must be explicit.)
I want to know how to make the function call both with and without using the additional
void*param.
To call a function with no argument, simply use () in the function call. But again, for a given function, you can't choose to call it with or without a parameter; the call has to match the definition. (Except perhaps for variadic functions like printf, but you still need a function pointer of the correct type, and a variadic function can't be called with no arguments.)
On line return ((void*)temp);
You are casting an int temp to a void*
Note that taking the address of temp is also invalid because you will get the warning warning: function returns address of local variable
You could change the funtion to return an int
int fun1(void *a) {
int temp = *((int*)a);
temp++;
return temp; // <-- Return the int value instead of a pointer.
}
And then change the calling function to
int x = fun1(&b); // <-- since fun1 now returns an integer there is no need to cast it.
You dereference a non-pointer value. This is the report. I copied the error message as the follow.
=========== Start of #0 stensal runtime message ===========
Runtime error: [dereferencing a non-pointer] Continuing execution can cause undefined behavior, abort!
-
- Reading 4 bytes from an illegit address (0x6).
-
- Stack trace (most recent call first) of the read.
- [0] file:/prog.c::23, 20
- [1] [libc-start-main]
-
============ End of #0 stensal runtime message ============