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 Overflow
๐ŸŒ
IncludeHelp
includehelp.com โ€บ c โ€บ void-pointer-as-function-argument.aspx
void pointer as function argument in C programming
Here, we will learn how to pass a string (character pointer) in a function, where function argument is void pointer. Consider the given example ยท #include <stdio.h> //function prototype void printString(void *ptr); int main() { char *str="Hi, there!"; printString(str); return 0; } //function definition void printString(void *ptr) { printf("str: %s\n",ptr); } Output ยท str: Hi, there! In this example the function parameter ptr is a void pointer and character pointer (string) str will be assigned in it and program will print the string through void pointer.
๐ŸŒ
Tufts University
cs.tufts.edu โ€บ comp โ€บ 40 โ€บ docs โ€บ function-pointers.html
Tufts: CS 40 Void and Function Pointers
Preamble: There are 3 unrelated meanings in C for the keyword void: As function return type: this function has no return value. As function parameter list in a declaration: this function takes exactly zero parameters. This is not the same as an empty parameter list โ€” that means takes an unspecified number of parameters.! As the target of a pointer: The pointer is generic, there is no information about what it points to.
๐ŸŒ
Deardevices
deardevices.com โ€บ 2019 โ€บ 05 โ€บ 07 โ€บ void-pointers-part1
3 Practical Uses of void Pointers in the C Language (part 1/3)
Obviously, when calling these functions, youโ€™ll need to pass in arguments of the appropriate type. Otherwise, your compiler will either try to implicitly convert the value or raise an error. In order to make a certain function usable for different data types, you can use parameters of type void *. Prominent Example: qsort from the C Standard Library.
๐ŸŒ
Rip Tutorial
riptutorial.com โ€บ void* pointers as arguments and return values to standard functions
C Language Tutorial => void* pointers as arguments and return...
In specific case of malloc() this is because with an explicit cast, the compiler may otherwise assume, but not warn about, an incorrect return type for malloc(), if you forget to include stdlib.h. It is also a case of using the correct behavior of void pointers to better conform to the DRY (don't repeat yourself) principle; compare the above to the following, wherein the following code contains several needless additional places where a typo could cause issues: ... have their arguments specified as void * because the address of any object, regardless of the type, can be passed in.
๐ŸŒ
Quora
quora.com โ€บ Is-there-ever-a-good-reason-to-have-a-function-parameter-be-a-void-pointer-in-C-or-C
Is there ever a good reason to have a function parameter be a void pointer in C or C++? - Quora
Answer (1 of 3): I was very proficient in C, however, I wrote my last C program 30 years ago. At that time it was necessary to have pointers to void. Although it has been a long time since I wrote my last code, C has not changed so much, therefore I think it is still necessary today. Anyway, I am...
๐ŸŒ
Uwinnipeg
theory.uwinnipeg.ca โ€บ programming โ€บ node87.html
Void pointers
#include <stdio.h> void use_int(void *); void use_float(void *); void greeting(void (*)(void *), void *); int main(void) { char ans; int i_age = 22; float f_age = 22.0; void *p; printf("Use int (i) or float (f)? "); scanf("%c", &ans); if (ans == 'i') { p = &i_age; greeting(use_int, p); } else { p = &f_age; greeting(use_float, p); } return 0; } void greeting(void (*fp)(void *), void *q) { fp(q); } void use_int(void *r) { int a; a = * (int *) r; printf("As an integer, you are %d years old.\n", a); } void use_float(void *s) { float *b; b = (float *) s; printf("As a float, you are %f years old.\n", *b); } Although this requires us to cast the void pointer into the appropriate type in the relevant subroutine (use_int or use_float), the flexibility here appears in the greeting routine, which can now handle in principle a function with any type of argument.
๐ŸŒ
Stanford
web.stanford.edu โ€บ class โ€บ archive โ€บ cs โ€บ cs107 โ€บ cs107.1202 โ€บ lab4
CS107 Lab 4: void * and Function Pointers
Instead what is exchanged are pointers to values. All pointers, regardless of pointee, are 8-byte addresses that are type-compatible with void*. Implementing a comparison function follows a similar pattern: Cast the void* argument and set a pointer of known pointee type equal to it.
Find elsewhere
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ c language โ€บ void-pointer-c-cpp
void Pointer in C - GeeksforGeeks
void pointers in C are used to ... used along with Function pointers of type void (*)(void) point to the functions that take any arguments and return any value. void pointers are mainly used in the implementation of data ...
Published ย  July 17, 2014
๐ŸŒ
Reddit
reddit.com โ€บ r/c_programming โ€บ void function pointer
r/C_Programming on Reddit: Void function pointer
January 5, 2024 -

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.

Top answer
1 of 5
19
meaning you can cast any function pointer to it and back I think there's a misunderstanding here. You can do that with any function pointer type, void(*)() isn't special here. From C99: 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 pointed-to type, the behavior is undefined. Note that these conversions might require a cast. There's also no special provisions for void(*)() to make it implicitly convertible with everything like there is for void*. The reason why your example works the way it does is that void(*)(int) is implicitly convertible to void(*)(), because they're pointers to compatible function types. The relevant passage is: If one type has a parameter type list and the other type is specified by a function declarator that is not part of a function definition and that contains an empty identifier list, the parameter list shall not have an ellipsis terminator and the type of each parameter shall be compatible with the type that results from the application of the default argument promotions. So because the default argument promotions turn char into int, void(*)(char) is not convertible, but void(*)(int) is.
2 of 5
5
void(*)() is not the same as void* - it's not just a generic function pointer that is compatible with all other function pointers. You can still cast the function pointer to a different pointer type, but you have to cast it explicitly. It's not automatically compatible. I think this part of the standard is what makes it complain: https://port70.net/%7Ensz/c/c11/n1570.html#6.7.6.3p15 specifically the part about "the type of each parameter shall be compatible with the type that results from the application of the default argument promotions". A char is promoted to an int and so your function needs to have an int argument in that position.
Top answer
1 of 2
1

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)

2 of 2
0

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:

  1. the pointer argument can be implicitly cast back to void*, there's no need to do it explicitly
  2. any pointer T* such that sizeof(T)==1 will work correctly: char is kind of traditional, uint8 is also fine
๐ŸŒ
TutorialsPoint
tutorialspoint.com โ€บ void-pointer-in-c
void Pointer in C
The malloc() function is available ... declaration of variables causes the memory to be allocated at the compile time. ... Void pointers are used to implement generic functions....
Top answer
1 of 2
4

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.

2 of 2
0

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);
}
Top answer
1 of 4
12

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.

2 of 4
2

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.)

๐ŸŒ
Unstop
unstop.com โ€บ home โ€บ blog โ€บ void pointer in c explained in detail with code examples
Void Pointer In C Explained In Detail With Code Examples // Unstop
March 1, 2024 - Because of this, it's crucial to ... as Function Arguments: The void pointers in C are frequently used as function pointers when sending generic data or objects to functions....
๐ŸŒ
Cprogramming
cboard.cprogramming.com โ€บ c-programming โ€บ 150306-passing-void-pointer-reference.html
Passing void pointer by reference
For example, in function, p is pointer to int, so *p is the int it points to. If you want to assign the value of i to the value p points to, just do: ... *p = i; No need for the a variable. Also, you don't necessarily need to malloc memory for this, you can just do: ... I am passing a void pointer by reference assigning a value to it.