C - Passing function with unknown params to another function, and calling it - c

I'm trying to achieve something like this:
void sum(int a, int b){ printf("result: %d", a+b); }
void callFunc(void (*funct)(...), ...)
{
va_list ars;
va_start(ars, funct);
funct(ars);
va_end(ars);
}
int main()
{
callFunc(sum, 2,3);
return 0;
}
But this doesn't work, because of needing of two va_lists, for funct params and arguments passed. However, even if i try to pass the sum function, it says:error: invalid conversion from 'void (*)(int, int)' to 'void (*)(...)'
So how to make this work good old C-style?

You can't do it like that. It's just simply not possible.
The best you can do (while keeping it generic) is change funct to take a va_list, much like vprintf. But that probably won't work very well for your purposes.
Alternatively, you can do a macro:
#include <stdio.h>
#define CALL_FUNC(func, ...) func(__VA_ARGS__)
void sum(int a, int b){ printf("result: %d", a+b); }
int main()
{
CALL_FUNC(sum, 2, 3);
return 0;
}

Related

Cannot print called float variables

I cannot print float variables when calling my functions. int variables print but floats won't print their proper value when passed to my function.
I tried to change the float to int and that worked
int main() {
int foo = 6;
call(foo);
}
void call(int bar) {
printf("%d", bar);
}
This worked and it does indeed print 6.
But, doing the same but with floats only prints out 0.00000:
int main() {
float foo = 6;
call(foo);
}
void call(float bar) {
printf("%f", bar);
}
How do I correctly call and then print float variables?
you need a forward declaration of call
void call(float integerrrr);
int main(){
float integerrrr=6;
call(integerrrr);
}
void call(float integerrrr){
printf("%f", integerrrr);
}
your compiler probably warned you about this
You could simply define call above main instead of below it. The compiler must have seen the declaration of functions when they are used, so a forward declaration like pm100 suggests is one way. Moving the whole definition above main is the another (that does not require a forward declaration).
#include <stdio.h>
void call(float integerrrr){
printf("%f", integerrrr);
}
int main(void){
float integerrrr = 6;
call(integerrrr); // now the compiler knows about this function
}
INT type variables i can print but float just does not
If your program actually compiles as-is it will use an old (obsolete) rule that makes an implicit declaration of undeclared functions when they are used. The implicit declaration would be int call(); - which does not match your actual function. The program (even the one that seems to be working) therefore had undefined behavior.
the compiler of c work from top to bottom so line by line,
so u will have to call the first function void call() then your main function:
void call(float integerrrr){
printf("%f", integerrrr);
}
int main(){
float integerrrr=6;
call(integerrrr);
}

C implementation for generic function with varargs

I need to write the implementation of a function that accept as parameters:
a function pointer
a list of parameters
The function prototype should be something like this :
void caller_imp( generic_function_pointer, varargs_list )
Suppose you have the following code example:
#define caller(function, ...) caller_imp(function, __VA_ARGS__)
int test (int a)
{
return a;
}
int test2(int a, int b)
{
return a+b;
}
void caller_imp(???,???)
{
???
}
int main(int argc, char **argv)
{
caller(test,33);
caller(test2,44,55);
return 0;
}
Of consequence im in need to write the proper implementation of the "caller_imp" function.
UPDATED DETAILS :
int test (int a)
int test2(int a, int b)
are only an example, the function pointer and the parameters coul be varying, for example :
int test3(int a,char *str)
should be considered valid
unfortunatly I dont know which function pointer will be called or the number of the parameters or their type.
In C++ I think I could do :
template<typename Function, typename... Params>
auto call_imp(Function function, Params... params)
->typename std::enable_if<std::is_same<void,decltype(function(params...))>::value,decltype(function(params...))>::type
{
function(std::forward<Params>(params)...);
}
Thanks in advance.
This is not supported in the C standard because there is no information available about what parameters a function expects. That is, given a function pointer alone, we cannot know whether the function expects one int argument, two int arguments, one int and one char * argument, or something else. Therefore, even if we had a way to dynamically construct an argument list, we would not know which argument list to construct.
If you do know which function requires which arguments, you can write specific code for each case:
#include <stdarg.h>
void caller_imp(void (*f)(void),...)
{
va_list ap;
va_start(ap, f);
if (f == (void (*)(void)) test)
{
int a = va_arg(ap, int);
((int (*)(int)) f)(a);
}
else if (f == (void (*)(void)) test2)
{
int a = va_arg(ap, int);
int b = va_arg(ap, int);
((int (*)(int, int)) f)(a, b);
}
va_end(ap);
}
Then the caller macro should convert the function pointer:
#define caller(function, ...) caller_imp((void (*)(void))(function), __VA_ARGS__)
If you do not know which function requires which arguments, it would be necessary to provide this information in some way, such as creating an enumeration of function types and requiring the caller to provide it.
You can do this to allow either 1 or 2 arguments of type int:
#define COUNT_ARGS(...) ( sizeof (int[]){__VA_ARGS__} / sizeof(int) )
#define caller(function, ...) (COUNT_ARGS(__VA_ARGS__) == 1 ? function : function##2) (__VA_ARGS__)
Usage:
caller(test, 1);
caller(test, 1, 2);
Please note that error handling is pretty non-existent here though...

C function pointer declaration omitting parameters

In the code, I omitted parameters for int (*bar) and assigned &foo, which as 3 arguments, to bar. (*bar) received the numbers and gave me a return value. I thought this is ok but I've heard that this is actually UB. How does (*bar) receive the numbers? Thx
#include <stdio.h>
int foo(int a, int b, int c){
return a+b+c;
}
int main(void) {
int (*bar)() = &foo;
printf("%d", bar(1, 2, 3));
return 0;
}
edit
When I pass more than three arguments to bar() (say 5 arguments), the program works. Where do the two extra arguments go?

Functions with infinitely many (unnamed) arguments - how to properly access these arguments?

I have a tough question for you, that I have been playing around with today, but for which I could not yet come up with an elegant solution.
We know, that functions of the form void func() take infinitely many arguments. Now I have put together a very simple minimal, working code snippet:
#include <stdio.h>
int func()
{
printf("%d, %d, %d, %d\n");
return 0;
}
int func() {
sucks(0 /* Offset */, 1, 2, 3, 4);
}
Alright, we can now call func() with as many arguments as we want. The questions that I am experimenting with atm is: how can we properly access the content of those arguments? The printf() function prints out something like this ... just to verify to ourselves that the arguments are actually there:
anonymous#melina:/tmp$ ./a.out
1 2 3 4
So now the question: The above snippet is a bit hackish. Is there a proper way to access these arguments? Or do you have to actually mess around with the stack pointer and inline assembly? I have, as a first try, thought about getting the stack pointer at the beginning of the function, e.g.,
uint64_t sp;
asm( "mov %%rsp, %0" : "=rm" ( sp ));
... and somehow use it, to guess where (in memory) those arguments actually are. However ... I have had no success so far.
Is there a proper way to access these arguments?
Yes. Specify a parameter list in the function definition with types and identifiers of the function.
You can do it "old style" (don't do it, it should not be used in new code):
int func(a, b, c, d)
int a;
int b;
int c;
int d;
{
printf("%d %d %d %d\n", a, b, c, d);
}
Or normal:
int func(int a, int b, int c, int d) {
printf("%d %d %d %d\n", a, b, c, d);
}
or using stdarg.h :
int func(int a, ...) {
va_list ap;
va_start(va, a);
int b = va_arg(va, int);
int c = va_arg(va, int);
int d = va_arg(va, int);
printf("%d %d %d %d\n", a, b, c, d);
va_end(ap);
}
or using stdarg.h from the second arg:
int func(int a, int b, ...) {
va_list ap;
va_start(va, b);
int c = va_arg(va, int);
int d = va_arg(va, int);
printf("%d %d %d %d\n", a, b, c, d);
va_end(ap);
}
or using stdarg.h from the third arg:
int func(int a, int b, int c, ...) {
va_list ap;
va_start(va, c);
int d = va_arg(va, int);
printf("%d %d %d %d\n", a, b, c, d);
va_end(ap);
}
stdarg.h needs at least one, first argument in the parameter list to be declared. So there is no way to handle function with unspecified number and type of arguments, but there is a way (stdarg.h) to handle function with at least 1 argument followed by unspecified number and type of arguments.
... functions of the form void func() take infinitely many arguments
This is not true. I don't think there is a C standard way to pass infinite number of arguments to a function.
Function of the form func() take unspecified number and type of arguments. They take a finite number of arguments, but the number is unspecified in the transaction unit where such function declaration is encountered. If the function definition takes 5 arguments, they take 5 arguments, otherwise undefined behavior. The number of arguments is not specified, if the function definition takes elipsis (, ...) in which case no information about the number or types of the parameters after the comma is supplied. (C11 6.7.6.3p9).
Or do you have to actually mess around with the stack pointer and inline assembly?
Yes, you have to "mess around" with implementation defined behavior.
From GCC docs 18.10:
... The ISO implementation of va_start takes an additional second argument. The user is supposed to write the last named argument of the function here.
However, va_start should not use this argument.
You need to specify the second argument to va_start. Maybe more on such topic can be found in this thread.
printf("%d %d %d %d\n");
This is undefined behavior. Once your program has undefined behavior, nasal demons start spawning in your room and are fighting for independence. It may have well defined behavior on your platform or implementation, but this is wrong, it's no longer a C language. If there is a "correct" behavior according to your mental model of the language, that model is simply wrong; from this thread. From the language point of view, nasal demons fight for independence and the program is invalid.
[...] functions of the form void func() take infinitely many arguments.
Nope.
Functions used without a prototype must be called according to their definition.
void foo(); // not a prototype
int main(void) {
// foo() must be called according to its definition
foo(12, 4, "bar", -42); // error (undetected by compiler)
foo("---", 12, 4, "bar", -42); // no error
}
void foo(const char *msg, int n, ...) { /* ... */ }
Note that pre-C89 function definitions had a different way of defining arguments. Desire for backwards compatability still allows for this syntax. I believe the same restrictions apply as above
void bar() /* pre-C89 syntax */
const char *msg;
int n;
{ /* ... */ }

How to define functions inside an array in C? [duplicate]

I have a struct that contains a declaration like this one:
void (*functions[256])(void) //Array of 256 functions without arguments and return value
And in another function I want to define it, but there are 256 functions!
I could do something like this:
struct.functions[0] = function0;
struct.functions[1] = function1;
struct.functions[2] = function2;
And so on, but this is too tiring, my question is there some way to do something like this?
struct.functions = { function0, function1, function2, function3, ..., };
EDIT: Syntax error corrected as said by Chris Lutz.
I have a struct that contains a declaration like this one:
No you don't. That's a syntax error. You're looking for:
void (*functions[256])();
Which is an array of function pointers. Note, however, that void func() isn't a "function that takes no arguments and returns nothing." It is a function that takes unspecified numbers or types of arguments and returns nothing. If you want "no arguments" you need this:
void (*functions[256])(void);
In C++, void func() does mean "takes no arguments," which causes some confusion (especially since the functionality C specifies for void func() is of dubious value.)
Either way, you should typedef your function pointer. It'll make the code infinitely easier to understand, and you'll only have one chance (at the typedef) to get the syntax wrong:
typedef void (*func_type)(void);
// ...
func_type functions[256];
Anyway, you can't assign to an array, but you can initialize an array and copy the data:
static func_type functions[256] = { /* initializer */ };
memcpy(mystruct.functions, functions, sizeof(functions));
I had the same problem, this is my small program to test the solution. It looks pretty straightforward so I thought I'd share it for future visitors.
#include <stdio.h>
int add(int a, int b) {
return a+b;
}
int minus(int a, int b) {
return a-b;
}
int multiply(int a, int b) {
return a*b;
}
typedef int (*f)(int, int); //declare typdef
f func[3] = {&add, &minus, &multiply}; //make array func of type f,
//the pointer to a function
int main() {
int i;
for (i = 0; i < 3; ++i) printf("%d\n", func[i](5, 4));
return 0;
}
You can do it dynamically... Here is a small example of a dynamic function array allocated with malloc...
#include <stdio.h>
#include <stdlib.h>
typedef void (*FOO_FUNC)(int x);
void a(int x)
{
printf("Function a: %d\n", x);
}
void b(int x)
{
printf("Function b: %d\n", x);
}
int main(int argc, char **argv)
{
FOO_FUNC *pFoo = (FOO_FUNC *)malloc(sizeof(FOO_FUNC) * 2);
pFoo[0] = &a;
pFoo[1] = &b;
pFoo[0](10);
pFoo[1](20);
return 0;
}
From the top of my head and untested.
// create array of pointers to functions
void (*functions[256])(void) = {&function0, &function1, &function2, ..., };
// copy pointers to struct
int i;
for (i = 0; i < 256; i++) struct.functions[i] = functions[i];
EDIT: Corrected syntax error as said by Chris Lutz.
You could do that while declaring your struct instance:
function_structur fs = { struct_field1,
struct_field2,
{function0, function1, ..., function255},
struct_field3,
... };
You cannot use this shortcut for initialize arrays after the array has been declared: if you need to do that, you'll have to do it dynamically (using a loop, a memcpy or something else).
If you want to post-initialize an array using form like {func1, func2, ...}, this can be accomplished in the following way (using GCC):
UPD (thanks to Chris Lutz for remarks)
Define a macro like this:
#define FUNCTION_VECTOR_COPY(destVec, sourceVec) memcpy(destVec, sourceVec, sizeof(sourceVec))
And pass source vector using Compound Literals, as follow:
#include <string.h>
...
void (*functions[256])();
...
FUNCTION_VECTOR_COPY (functions, ((void(*[])()) {func1, func2, func3}));

Resources