C: Passing a function pointer in a function it is passed to - c

I'm trying to write a mapping function that takes a function pointer, and passes it to another function, but gcc is yelling at me.
Here is an idea of what I'm trying to do.
void map(T thing, void apply(int a, int b, void *cl), void *cl);
void function(T thing, void apply(int a, int b, void *cl), void * cl)
{
for(int i = 0; i < 10; i++)
{
map(thing, apply, cl);
}
}
gcc's complaint:
warning: passing argument 2 of 'map' from incompatible pointer type
Any ideas?

In order to help with this problem we'd need to see the declaration / signature of the map function. Almost certainly there is a slight difference in the function signature. The easiest way to resolve this is to typedef out a function pointer type and use it in both functions.
typedef void (*apply)(int,int,void*);

You can't pass functions around. You need to pass pointers to functions instead.
void map(T thing, void (*apply)(int a, int b, void *cl), void *cl);
void function(T thing, void (*apply)(int a, int b, void *cl), void * cl)
{
/* ... */
map(thing, apply, cl);
/* .... */
}

It's just complaining that the function pointer type expected by map's second argument is different from that of apply. If you either change that type, or (if safe) cast, then it'll be fine.

It works for me with gcc 4.3.3 and -Wall.
While I think all versions of C that ever existed rewrote function "value" parameters to be pointers, you could use a more traditional declaration:
void function(T thing, void (*f)(int a, int b, void *cl), void * cl)
But, like I said, your example works fine for me, unchanged except for typedef int T, and map(1, ...)

Related

How to convert array to arguments for a function in C?

void test(int a,int b,int c)
{
printf("%d;%d;%d\n",a,b,c);
}
void run(void(*function)(int,int,int),int[] args,int sizeArgs)
{
function(#passing args);
}
run(test,(int[]){4,6,9});
I need a function like run that accepts another function and an array of arguments. It is necessary that the run function enumerates arguments and then calls the passed function.
You could tweak the function to the following:
typedef void func3_t (int, int, int);
...
void run (func3_t* func, int size, const int args[size])
The function pointer syntax in C is hard to read, so therefore use typedef. The typedef here declares a function type and then we let the function take a function pointer to such a function.
I changed the args to const since they shouldn't be modified, this is called const correctness and is overall good practice. By placing the size parameter before the array, we can let the array refer to that variable. (This gives a pointer to a variable-length array, VLA.)
The function body would be trivial, just do some error check and otherwise leave it to the caller to provide the correct array size:
if(size==3)
{
func(args[0], args[1], args[2]);
}
Here's a complete example:
#include <stdio.h>
typedef void func3_t (int, int, int);
void test(int a, int b, int c)
{
printf("%d;%d;%d\n",a,b,c);
}
void run (func3_t* func, int size, const int args[size])
{
if(size==3)
{
func(args[0], args[1], args[2]);
}
}
int main (void)
{
run(test, 3, (int[]){4,6,9});
}
If code such as this is meaningful, well that's another story...
To create a completely variadic function which is also type safe... well, I would consider changing the program design first of all, because it likely does not make any sense. You could replace the function with a very evil macro such as this:
// BAD IDEA
#define run(func, ...) _Generic(&(__VA_ARGS__), \
int(*)[3]: _Generic((func), void(*)(int,int,int): (func)) ) \
(__VA_ARGS__[0], __VA_ARGS__[1], __VA_ARGS__[2])
int main (void)
{
run(test, (int[]){4,6,9});
}
This is actually type safe and can be expanded to support other function types... but if you are a C beginner then forget all about this macro, since it is using some rather advanced language features.
The array can be passed as an agrument to a function by just passing the name of array.
int a[];---> array
fun(a);--->function calling
so we are actually passing the base address of the array.

Possible to pass a non-void function pointer as a void function pointer?

Say I have a function foo() which accepts a pointer to a void function as a parameter.
void foo(void (*bar)(int)) {
bar(5);
}
If I have a non-void function f(int)
bool f(int i) {
// ...
return true;
}
Is there a way to cast f in such a way that it can be passed to foo() without warnings?
My current solution is to define a function void g(int i) {f(i);} and pass g to foo, but this seems inefficient to me. It seems like there should be a way to cast f in such a way that its return value is thrown out.
If this isn't possible, why not?
Sorry if I'm missing the point, but this compiles without warnings with gcc, even with -Wall:
typedef void (*p_bar) (int);
void foo (p_bar bar)
{
bar(5);
}
int f (int i)
{
printf ("In f(), arg=%d\n", i);
return 1;
}
int main()
{
foo ((p_bar)f);
}
I can see why this is a suspicious cast but, in fact, I suspect that it will work fine for integers on most modern compilers. Integers are nearly always returned in a register.
But, as I say, maybe I'm missing something.

function pointer with generic argument type

for knowledge sake, I would like to know if something like this is possible:
2 function:
static int func1(int *a, int b){
...
}
static int func2(double *a, int b){
...
}
I would like to declare a function pointer and point it to one of these function. However the arguments of these functions are of different type. So I tried:
static int (*func_ptr)(void *arg1, int arg2);
static void *Argument1;
static int Argument2=5;
int main(){
double arg1_d;;
int arg1_i;
...
if(want_func2){
Argument1=(double *) &arg1_d;
func_ptr=func2;
run(func_ptr);
}
else{
Argument1=(int *) &arg1_i;
func_ptr=func1;
run(func_ptr);
}
return 0;
}
static int run(int *(function)(void *,int )){
function(Argument1,Argument2);
}
However, when compiling I get the warning:
warning: assignment from incompatible pointer type
when
func_ptr=func2;
func_ptr=func1;
Is there anyway to create a function pointer with a generic type argument?
You are on the right track. But, in order to achieve what you want, your functions should have a void* parameter and cast it internally to int or double.
No. You need the if...else to use such a thing correctly anyway, so just store separate function pointers and use the correct pointer in each piece of code.

How to put parameters(2nd grade array) to sub() ,,...void func( int* Array2nd)

void HowToPutParameters( XXXXXX) // how to put parameters in XXXXXX
{
array[0][0]=5;
}
void main()
{
int array[2][2]={{1,2},{3,4}};
HowToPutParameters(&array[0][0]); // &array[0][0] is correct or &array[0]
}
// I wana put this array to HowToPutParameters;
// 1.I am not sure "&array[0][0] or &array[0]" are correct,The compiler seems identify;
// I've tried void HowToPutParameters(int *array ) ==> compile failed
// I've tried void HowToPutParameters(int *array[][] ) ==> compile failed
// My compiler is MPLAB X IDE V1.8 , Chip is Microchip>PIC32MX795F512
If you want use pass two dimensions array params,use:
void func(int (*a)[2]);// tell the function the first dimension size!
func(array);
It is the same as:
void func(int a[][2]);
func(array);
If you pass &array[0][0], it means you pass a pointer point to a int.
void func(int *element);
Like this, in your code you are only passing a pointer to an int element of the array, not the array itself.
void HowToPutParameters(int* element)
And you should always use int main instead of void main.

generic programming in C with void pointer

Even though it is possible to write generic code in C using void pointer(generic pointer), I find that it is quite difficult to debug the code since void pointer can take any pointer type without warning from compiler.
(e.g function foo() take void pointer which is supposed to be pointer to struct, but compiler won't complain if char array is passed.)
What kind of approach/strategy do you all use when using void pointer in C?
The solution is not to use void* unless you really, really have to. The places where a void pointer is actually required are very small: parameters to thread functions, and a handful of others places where you need to pass implementation-specific data through a generic function. In every case, the code that accepts the void* parameter should only accept one data type passed via the void pointer, and the type should be documented in comments and slavishly obeyed by all callers.
This might help:
comp.lang.c FAQ list ยท Question 4.9
Q: Suppose I want to write a function that takes a generic pointer as an argument and I want to simulate passing it by reference. Can I give the formal parameter type void **, and do something like this?
void f(void **);
double *dp;
f((void **)&dp);
A: Not portably. Code like this may work and is sometimes recommended, but it relies on all pointer types having the same internal representation (which is common, but not universal; see question 5.17).
There is no generic pointer-to-pointer type in C. void * acts as a generic pointer only because conversions (if necessary) are applied automatically when other pointer types are assigned to and from void * 's; these conversions cannot be performed if an attempt is made to indirect upon a void ** value which points at a pointer type other than void *. When you make use of a void ** pointer value (for instance, when you use the * operator to access the void * value to which the void ** points), the compiler has no way of knowing whether that void * value was once converted from some other pointer type. It must assume that it is nothing more than a void *; it cannot perform any implicit conversions.
In other words, any void ** value you play with must be the address of an actual void * value somewhere; casts like (void **)&dp, though they may shut the compiler up, are nonportable (and may not even do what you want; see also question 13.9). If the pointer that the void ** points to is not a void *, and if it has a different size or representation than a void *, then the compiler isn't going to be able to access it correctly.
To make the code fragment above work, you'd have to use an intermediate void * variable:
double *dp;
void *vp = dp;
f(&vp);
dp = vp;
The assignments to and from vp give the compiler the opportunity to perform any conversions, if necessary.
Again, the discussion so far assumes that different pointer types might have different sizes or representations, which is rare today, but not unheard of. To appreciate the problem with void ** more clearly, compare the situation to an analogous one involving, say, types int and double, which probably have different sizes and certainly have different representations. If we have a function
void incme(double *p)
{
*p += 1;
}
then we can do something like
int i = 1;
double d = i;
incme(&d);
i = d;
and i will be incremented by 1. (This is analogous to the correct void ** code involving the auxiliary vp.) If, on the other hand, we were to attempt something like
int i = 1;
incme((double *)&i); /* WRONG */
(this code is analogous to the fragment in the question), it would be highly unlikely to work.
Arya's solution can be changed a little to support a variable size:
#include <stdio.h>
#include <string.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[size];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int array1[] = {1, 2, 3};
int array2[] = {10, 20, 30};
swap(array1, array2, 3 * sizeof(int));
int i;
printf("array1: ");
for (i = 0; i < 3; i++)
printf(" %d", array1[i]);
printf("\n");
printf("array2: ");
for (i = 0; i < 3; i++)
printf(" %d", array2[i]);
printf("\n");
return 0;
}
The approach/strategy is to minimize use of void* pointers. They are needed in specific cases. If you really need to pass void* you should pass size of pointer's target also.
This generic swap function will help you a lot in understanding generic void *
#include<stdio.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[100];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int a=2,b=3;
float d=5,e=7;
swap(&a,&b,sizeof(int));
swap(&d,&e,sizeof(float));
printf("%d %d %.0f %.0f\n",a,b,d,e);
return 0;
}
We all know that the C typesystem is basically crap, but try to not do that... You still have some options to deal with generic types: unions and opaque pointers.
Anyway, if a generic function is taking a void pointer as a parameter, it shouldn't try to dereference it!.

Resources