Why is my function in a function being regarded as a pointer? - c

I am a bit familiar with pointers and function pointers, perhaps, but this is confusing. I have a function and here is its, function header;
void report(List*, bool check(Item*, void*), void*);
The actual function is implemented same as the prototype in the header file. The prototype in main is: bool check(Item*, void*);. Basically this just reports things from a list, based on the return value of check. When calling the function in main.c, I use report(list, check(item, specificArg), arg); The only reason I am using void pointers, is because arg/specificArg could be whatever I want basically. But the problem is in check(item, specificArg), where the compiler reports:
incompatible integer to pointer conversion passing 'bool' to parameter of type 'bool (*)(Item *, void *)'

When doing check(item, specificArg) you're actually calling the function and passing its return value to the call to report, while it expected a function pointer instead.
The correct call syntax is:
report(list, check, arg);

The function prototype
void report(List*, bool check(Item*, void*), void*);
takes 3 arguments,
A List * which is unnamed
A pointer to a function that takes an Item * and a void * and returns a bool -- this parameter is named check
A void * which is also unnamed.
You are calling it with report(list, check(item, specificArg), arg) Notice the second parameter you are passing is a bool --> the result of the call to check(item, specificArg). Thus the mismatch.

this prototype is not correct:
void report(List*, bool check(Item*, void*), void*);
Suggest this prototype
void report( List*, bool, Item*, void*, void* );
then the signature would be:
void report( List* pMyList, Item* pmyItem, void* parm1, void* parm2 )
Then inside the report function:
bool mybool = check( pMyItem, parm1 );
However, if you want to pass different functions then suggest using the following prototype:
void report(List*, (bool (*)(Item*, void*)), void*);

Related

What does `typedef` mean in this context

I am sure this question has been asked before. But I am wondering what does the typedef mean in this code:
typedef long (*HASH_CONS_HASH)(void *);
typedef bool (*HASH_CONS_EQUAL(void *, void *));
So far I understand:
HASH_CONS_HASH is a function that takes a void* and returns long
HASH_CONS_EQUAL is a function that takes two arguments of type void* and returns bool
But what does typedef mean here? is it necessary?
It declares the function pointer type.
now you can define HASH_CONS_HASH func1; where func1 is a pointer to the function returning long and not taking any parameters
or
HASH_CONS_EQUAL func2; where func2 is a pointer to function returning bool and taking two void pointer as parameters.

C how to get argument of type pointer to function from va_arg

I know that if I passed an argument like void (*func)(void *) to a variadic function, I can retrieve the argument like:
void (*func)(void *) = va_arg( args, void (*)(void) );
What if I pass something like void (** func)(void *)? What is the correct syntax to retrieve an argument of this type using va_arg?
Being frankly, your code is not standard-compliant. There is a tiny restriction for second argument of va_arg() macro:
... The parameter type shall be a type name specified such that the type
of a pointer to an object that has the specified type can be obtained
simply by postfixing a * to type. ...
According to this, notation like void (*)(void *) is unacceptable in this case. Since simple appending of * won't give you pointer to pointer to function. You may use only typedef-ed aliases:
typedef void (*func_ptr)(void *);
typedef void (**ptr_to_func_ptr)(void *);
func_ptr var1 = va_arg(ap, func_ptr);
ptr_to_func_ptr var2 = va_arg(ap, ptr_to_func_ptr);
Same as you've mentioned:
typedef void (** func_t)(void *);
func_t ppf;
va_list vl;
va_start(vl,n);
ppf = va_arg(vl, func_t);
...
To help pointer-to-function, I always use typedef as follows:
typedef void VoidFn(void *); // Function accepts void * and returns nothing.
That declares the prototype of the function as a typedef, allowing the use of the typedef elsewhere.
That way if you have this function:
void SomeFn(void *) {...}
you can declare this pointer:
VoidFn *fnPtr = &SomeFn; // A pointer to such a function.
This then makes it easier to change the prototype independently of the pointer, helping more... sophisticated constructs:
typedef void *VoidPtrFn(void *); // Function takes a void *, returning a void *
void *SomeOtherFn(void *) { ... }
VoidPtrFn *otherFnPtr = &SomeOtherFn;
VoidPtrFn **otherFnPtrPtr = &otherFnPtr;

the difference between void (*xmlHashScanner) and void *xmlHashScanner

What is the difference between void (*xmlHashScanner)(void *payload, void *data, xmlChar *name) and void *xmlHashScanner(void *payload, void *data, xmlChar *name) in C?
Why do they behave differently?
xmlHashScanner is a user-defined function in the library libxml2.
When I try to redefine this function with a little different prototype: void *xmlHashScanner instead of void (*xmlHashScanner) I have the following error:
error: ‘xmlHashScanner’ redeclared as different kind of symbol
void *xmlHashScanner(void *payload, void *data, xmlChar *name)
^
In file included from /usr/include/libxml2/libxml/parser.h:18:0,
from /home/solar/Bureau/parser/src/diam_dict.c:12:
/usr/include/libxml2/libxml/hash.h:88:16: note: previous declaration of ‘xmlHashScanner’ was here
typedef void (*xmlHashScanner)(void *payload, void *data, xmlChar *name);
I wonder what is the difference between two of them.
void (*xmlHashScanner)(...) is a prototype for a function pointer returning nothing (void) whereas void *xmlHashScanner(...) is a prototype for a function returning a void*
void (*xmlHashScanner)(void *payload, void *data, xmlChar *name)
declares xmlHashScanner as a pointer to a function returning void, whereas
void *xmlHashScanner(void *payload, void *data, xmlChar *name)
declares xmlHashScanner as a function returning a pointer to void.
In both declaration and expression syntax, the unary * operator has lower precedence than the postfix [] subscript and () function call operators, so
T *a[N]; // a is an N-element array of pointer to T
T (*a)[N]; // a is a pointer to an N-element array of T
T *f(); // f is a function returning a pointer to T
T (*f)(); // f is a pointer to a function returning T
So you are comparing this:
void *xmlHashScanner(void *payload, void *data, xmlChar *name);
with this:
typedef void (*xmlHashScanner)(void *payload, void *data, xmlChar *name);
The first is a declaration for a function, and the second one is a typedef (defines a type). A function and a type are vastly different things; they are used for different purposes:
A function can be called
A type can be used for making a variable, which can then participate in calculations
This is what your compiler means by "a different kind of symbol" - there is no context (unless by accident) where these pieces of code can do anything similar. Consider, for example, tho pieces of code - 42 and &&. They have nothing in common - they are two different kinds of things.
To understand the details of the declaration, which are a bit confusing, use the right-left rule, which is also implemented here.
typedef void (*xmlHashScanner)(whatever) means xmlHashScanner type is a pointer to a function with whatever arguments returning void
void *xmlHashScanner(whatever) means xmlHashScanner is a function with whatever arguments, which returns void *

function pointer in C, with or without *?

is there difference between with or without * for function pointer in C?
my function pointer declaration like this
typedef void (*DListVisitNode) (Node*, void*);
void DListTraverse( NodeList* , DListVisitNode , void*);
i have code like these
void print_index( Node* node, void* ctx)
{
printf("index:%d\n", node->index);
}
void* print_content( Node* node, void* ctx)
{
printf("content:%s\n", node->content);
}
void DListTraverse(NodeList* nodelist, DListVisitNode visit_func, void* ctx)
{
Node* cur_node = nodelist->headnode;
while( cur_node != NULL)
{
visit_func( cur_node, ctx );
cur_node = cur_node->nextnode;
}
}
DListTraverse( nodelist, print_content, NULL );
DListTraverse( nodelist, print_index, NULL );
both of DListTraverse works, but the one with * throws warning like this
warning: passing argument 2 of ‘DListTraverse’ from incompatible pointer type
i would simply delete the * afterward, but what's the difference between them?
print_content is defined as returning a void* i.e. a generic raw pointer.
print_index is defined as returning void i.e. without any results.
These are different signatures. Only print_index matches DListVisitNode.
My coding style is to define signature thru typedef like
typedef void signature_t (int);
Notice that no pointer is involved above. This names the signature of functions with one int argument and no results.
then, when needing pointers to such functions of above signature, use signature_t*
What is true is that the name of a function is like the name of an array; the language implicitly convert these to pointers. So DListTraverse(nodelist, print_content, NULL) is understood like DListTraverse(nodelist, &print_content, NULL)
You should enable all warnings on your compiler; with gcc that means giving -Wall -Wextra as program arguments to the compiler.
You've declared print_content as returning a void * (a pointer), which means it doesn't match DListVisitNode. However, as the function doesn't actually return anything (no return statement), you should be gatting another warning about that.
You may be confused about the difference between the following to typedefs:
typedef void (*DListVisitNode) (Node*, void*);
typedef void * (*DListVisitNode) (Node*, void*);
Or equivalently, between the following two types:
void (*) (Node *, void *)
void * (*) (Node *, void *)
The former is a pointer to a function returning void, the latter is a pointer to a function returning void *. Each of your print functions is an example of one such function.
Naturally, function pointers of different types are incompatible and not implicitly convertible, as surely this would make no sense: You can't just pretend that a function actually has a completely different signature and expect to be able to call it in any meaningful way. It would be like pretending that a bicycle is a car and then trying to refuel it at a gas station.
typedef void (*DListVisitNode) (Node*, void*);
Defines a pointer to an function as an type which takes two parameters Node * and void * and returns a void.
Once you use the above statement, DListVisitNode can be used as an type, the exact type is as mentioned above.
void* print_content( Node* node, void* ctx)
returns a void * and not a void.
C is a strongly typed language, the c standard mandates that any type violations must be reported by the compiler, hence there is a type mismatch and the compiler reports it to you. Basically, if your function doesn't return anything use the return type as void or if you intend to return a particular type then use that specific type as an return type.

typedef function return value in C

Please help me understand what this typedef is doing??
typedef void (xyz) (void *data);
extern struct x* FUNCTION(xyz *ptr);
Here is my understanding: in 1st line xyz is a function returning void and taking void pointer as an argument. But I cant interpret 2nd line with this understanding.
Any input is appreciable.
There is an external function called FUNCTION which takes a pointer to an xyz function as parameter and returns a pointer to a struct x.
The first line defines xyz to be the type of a function returning void and taking one argument of type void*. You can actually omit the name data, as it does nothing.
Since there are no raw function types in C that you can declare directly, you can only use pointers to xyz, as indeed you have xyz * ptr.
It is more common to include the pointer in the typedef:
typedef void (*fptr)(void*);
void call(fptr f, void * arg) { f(arg); }
void some_function(void * data); // whatever
int main()
{
void * p = malloc(8);
call(some_function, p);
}
The second line declares a function that takes an xyz* as an argument and returns a pointer to a struct x, with external linkage.

Resources