everyone, I have this piece of the code:
void foo(int var, int var1)
{
printf("%d\n", var);
printf("%d\n", var1);
}
void foo_for_foo( void (*some_function)(int, int))
{
int x = 5;
some_function(x, x);
}
int main()
{
void (*ptr_foo); // <- look here
ptr_foo = &foo;
foo_for_foo(ptr_foo);
return 0;
}
does it matter how do I define pointer to function:
1) void (*ptr_foo);
2) void (*ptr_foo)(int, int);
my compiler receives both versions
thanks in advance for the explanations of the difference
The two forms are not equivalent.
void (*ptr_foo) is not a function pointer at all. It's a normal, non-function void pointer. The parentheses are superfluous and misleading. It's exactly as if you had written void* ptr_foo.
void (*ptr_foo)(int, int) is the proper way to declare a function pointer to a function taking two ints and returning void.
The only reason that this works is because in C, void pointers are implicitly convertible to any other type of pointer. That is, you can assign any other pointer to a void*, and you can assign a void* to any other pointer.
But the fact that this works in this example is essentially an accident of syntax. You cannot in general replace void (*foo)(int, int) with void (*foo).
If you try doing that with some_function in the argument list to foo_for_foo, your compiler will complain when you try to invoke some_function because it is not a function pointer.
Similarly, if your foo function happened to return an int instead of void, you would notice the problem right away. Declaring ptr_foo as int (*ptr_foo) would have resulted in an error on the statement ptr_foo = &foo because unlike void pointers, int pointers are not implicitly convertible to other pointer types.
In short, always use the second form. It is the only one that is correct in general, despite this fluky case.
The statement void (*ptr_foo); declares a variable of type void *. The function pointer is cast to this type in the statement ptr_foo = &foo; and back to a pointer to the proper function pointer type in the call to foo_for_foo. If you compile with gcc -Wall (or whatever extra paranoid settings your compiler supports) you should see a warning about this conversion.
Related
I wrote these lines of code expecting them to work just fine but I keep getting an error that says "invalid use of void expression" and I have no clue why
int main(){
int a=12;
void* ptr = &a;
printf("%d",*ptr);
}
I thought void pointers can point to any type of data so what's the issue here? I even tried to cast the void pointer to an integer pointer but I still get the same error.
I thought void pointers can point to any type of data so what's the issue here.
A void * can point to any type of data1. But it only remembers the address, not the type. To use it with *, you must tell the compiler what type to use:
int a = 12;
void *ptr = &a;
printf("%d\n", * (int *) ptr); // Use cast to specify type.
During execution, the program will not remember that ptr was assigned an address from an int and automatically know to load an int in the printf call. During compilation, the compiler will not remember this either. To use the pointer to access data, you must convert it back to an appropriate type, then use that.
Footnote
1 A pointer should retain all the qualifiers of any object it is set to point to. A pointer to a const int x or volatile int x ought to be assigned to a const void *p or a volatile void *p, respectively, not a void *p without the qualifiers.
You can not dereference a void pointer, the underlying type (void) is incomplete.
You should either use a different type for your pointer (such as int*) or you should cast your void pointer to a complete type (again, probably int*).
You can't dereference a void*, as you've seen, but casting it to an int* most definitely works:
printf("%d",*(int*)ptr);
OnlineGDB demo
Sorry, but I'm a bit confused about using function pointers. I typed 3 functions which use function pointer in different ways, but incredibly they all worked.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef int(*pfun)(int a, int b);
int add(int a, int b)
{
return a + b;
}
int f1()
{
pfun fun = add;
return fun(3, 4);
}
int f2()
{
pfun fun = &add; //Why did't compiler report an error?
return fun(3, 4); //Why it could work? The value in fun should be a pointer of function pointer.
}
int f3()
{
pfun fun = &add;
return (*fun)(3, 4); //Why did't compiler report an error?
}
int main()
{
printf("%d,%d,%d\n", f1(),f2(),f3());
system("pause");
return 0;
}
The output is 7,7,7 with no compile error in VS2017.
In f2 your comment is wrong. &add could not possibly be a pointer-to-pointer; what pointer object would it point to? Likewise, given char array[N];, &array is not a pointer-to-pointer. It has pointer-to-array type. Both function and array type identifiers evaluate to pointers (pointer-to-function or pointer-to-first-element, respectively) in most contexts, but that does not mean that they have pointer type themselves.
In f3, *fun is an expression evaluating to a function, which always converts implicitly to a pointer to the function. There is simply no such thing as an expression with function type. Therefore, ****************fun also evaluates to the same thing as fun (a pointer to add).
Note that the function call operator () takes as its operand an expression with pointer-to-function type. Whenever you call a function by its identifier, you are using a function pointer.
Per the language, none of these forms are any more "right" than any other, but I think most C programmers find use of & and * operators at best redundant (if not misleading) with functions, and would consider f1 the best.
There is no difference between add and &add. Both expressions represent the adress of the function.
As for
fun(3, 4);
// vs.
(*fun)(3, 4);
it doesn't matter whether the function pointer is dereferenced implicitly or you do it explicitly.
I found this function definition
void *func(void *param) {
}
Actually, I have a certain confusion regarding this function definition. What does void * mean in the return type of the function as well as the argument. I am a beginner in C. So please don't mind. Thank you
void *func(void *param) {
int s = (int)param;
....
}
Well looking at the above program which I found. I think it should have been
int *s = (int *)param;
isn't it? I am confused
void * means it's a pointer of no specific type, think of it as a generic pointer, unlike say int * an int pointer.
You can cast it into a different type if need be (for instance if you are going to do pointer arithmetic with the pointer).
You might find this SO question of use: Concept of void pointer in C programming
It simply means that the function func takes one parameter which is a pointer (to anything) and returns a pointer (to anything). When you use a void *, you are telling the compiler "this is a pointer, but it doesn't matter at this point what it's a pointer to".
When you want to actually use the data it's pointing to, you need to cast it to a pointer to some other type. For example, if it points to an int, you can create an int * variable and dereference that:
int *int_ptr = (int *)param;
// now (*int_ptr) is the value param is pointing to
you can think of it as a raw pointer, nothing more than an address, think about it, pointers are nothing more than address right, so they should all be of equal size, either 32 or 64 bits in most modern systems but if thats the case why do we say int * or char * or so on if they are all the same size, well thats because we need of a way to interpret the type we are pointing to, int * means when we dereference go to that address and interpret the 4 bytes as an int or char * means when we dereference go to that address and get a byte, so what happens when you dereference a void * well you get warning: dereferencing ‘void *’ pointer basically we really can't and if you do its affects are compiler dependent, the same applies when we do arithmetics on it.
So why bother using them? well I personally don't and some groups dont particularly like them, fundamentally they allow you to create fairly generic subroutines, a good example would be memset which sets a block of memory to a certain byte value, its first argument is a void * so it won't complain whether giving a char * or int * due note that it works on a per byte basis, and you need to properly calculate the total size of the array.
void *func(void *param) {
}
param is a void pointer means it is a pointer of any reference type. since a void pointer has no object type,it cannot be dereferenced unless it is case.
so void *param;
int *s=(int*)param;
here since param is an pointer variable so you will have to cast it as a pointer variable.not to a int type as you did there.
e.g.
int x;
float r;
void *p=&x;
int main()
{
*(int *)p=2;
p=&r;
*(float*)p=1.1;
}
in this example p is a void pointer. now in main method I have cast the p as a int pointer and then as a float pointer so that it can reference to first a integer and then a float.
Returning a pointer of any type. It can be of any datatype.
What's going on in this function prototype? Obviously the void parameter with some sort of typecasting is confusing...
int *my_func(my_struct *m, void (*m_op)(my_struct *v, void arg));
The second argument to the function my_func is a pointer to a function that returns no value (void), but which takes two arguments, a my_struct pointer and ... and (an invalid) void. The latter should probably be void *arg; you cannot have a variable or argument of type void. As it stands, the code should not compile.
This prototype declares a function, my_func that returns int *. It takes two arguments, the first being of type my_struct * and the second of the strange type void (*)(my_struct *, void). This means that the second argument is a pointer to a function that returns void and takes 2 arguments itself, a pointer to my_struct and void (I assume that was a typo and it takes a void *).
This little article explains how to parse C declarations in a spiral-like motion. Constructing is done in the reverse.
My suggestion - always try to split declarations into smaller ones - in that case code will be more readable. In this case you could re-write code as:
typedef struct {} my_struct;
typedef void (* m_op_function)(my_struct * v, void * arg);
int * my_func(my_struct * m, m_op_function f);
And as everybody said- it's almost 99,99% typo here regarding second parameter to m_op_function- it is possible void* - so that you can pass any pointer to it - be it (char*), (int*), (my_struct*), or anything else. Simply just cast pointer.
Is it safe to convert an int pointer to void pointer and then back to int pointer?
main()
{
...
int *a = malloc(sizeof(int));
...
*a=10;
func(a);
...
}
void func(void *v)
{
int x=*(int *)v;
...
}
Is this a valid way of getting the integer value back in the function?
Yes, it is safe. The Standard says so (6.3.2.3/1)
A pointer to void may be converted to or from a pointer to any
incomplete or object type. A pointer to any incomplete or object
type may be converted to a pointer to void and back again;
the result shall compare equal to the original pointer.
It is "safe" insofar as the pointer resulting from the int => void => int conversion will be the same as the original pointer.
It is not "safe" insofar as it's easy to get wrong and you have to be careful (that said, this type of code is often necessary in C, since void* is often used as a form of generalization).