How to allow variable parameters passed to function - c

I have a function that accepts 3 parameters, however I also want it to only accept the first two and not care about the third. How can I do this in C. I tried just declaring the function in the header file as void list()
thinking this might imply that we don't care how many parameters but this didn't work.
void list(uint8_t _pin, unsigned int time, unsigned long tasks)

What you want is called Variadic function. It can accept variable number of arguments.
**Famous examples: printf()/scanf()
These functions contain an ellipsis (…) notation in the argument list, and uses special macros to access the variable arguments.
The most basic idea is to write a function that accepts a variable number of arguments. So, it must be declared with a prototype that says so.
The syntax of ISO C requires at least one fixed argument before the …. thus, we write the fixed arguments as usual, and then add the … notain at the end of the parameter list to indicate the possibility of additional arguments. For example,
int func (const char *a, int b, …)
{
…
}
defines a function func() which returns an int and takes two required arguments, a const char * and an int. These are followed by any number of anonymous arguments.
You can check the On-line GNU manual for more details.

Here is a trick explained in SO here : C default arguments.
You can make third parameter as default in function declaration as follows:
typedef struct {
uint8_t _pin;
unsigned int time;
unsigned long tasks;
} f_args;
double var_f(f_args in){
uint8_t _pin = in._pin? in._pin : 8;
unsigned int time = in.time ? in.time : 3;
unsigned long tasks =in.tasks? in.taska : 0;
return f_base(i_out, x_out);
return list(_pin, time, tasks);
}
#define list(...) var_f((f_args){__VA_ARGS__});
So you can call your function as follows:
list(2,5);

A different solution to your problem without variable parameters is to do something like this:
void list(int argc, char **argv);
You have two parameters always, however what changes is the contents of argv and the count of what is inside it. You might have seen this in the entry point (main function) of other C programs. The parameters argc, argument count, and argv, argument vector, give the number and values of what you need.
Then inside list you could do something like:
if (argc == 2)
do_something;
else if(argc == 3)
do_something_else;
else
whatever;

Related

Point to functions with different arguments using the same pointer

I am trying to build a parser to a given input, there are 8 possible commands. So I figured that instead of using the ugly technique of a case switch block like that:
switch(command)
case cmd1:
.... /*call a function that do cmd1*/
case cmd2
..../*call a function that do cmd2*/
I will define in a header an array of structs, each one contains the name of the function, and a pointer to a function:
typedef struct command_info
{
char *name;
void (*func)(int)
};
command_info command_table[] = {{"func1", &func1}, {"func2", &func2} }
So that I can switch to the more elegant:
int i;
for(i = 0; i < COMMAND_TABLE_LENGTH; i++)
if(!strcmp(command_table[i].name, command))
command_table[i].func(2);
My only problem is, that the functions have different parameters (all return void). This is not a problem for me since I can check if the function is func1 or func2 search for one int argument for example, and if it is func3 or func4 search for two (still more compact than case switch). But the function pointer only points to a function with a certain type and amount of arguments. How can I make a universal pointer that can point to any function?
But the function pointer only points to a function with a certain type and amount of arguments.
How can I make a universal pointer that can point to any function?
In OP's limited case, use void (*func)().
Any function pointer can be converted with a type cast to another function pointer and retain an equivalent function address. #Jonathan Leffler
int (*foo)(int) = (int (*)(int)) sqrt;
double (*sq)(double) = (double (*)(double)) foo;
printf("%f\n", sq(2)); // prints 1.414214
A function pointer need not provide a function parameter signature.
// No parameter info
// vv
int (*foo)() = (int (*)()) sqrt;
OP has "functions have different parameters (all return void)", so in OP's case code could use a limited universal function pointer of void (*func)() and lose parameter checking.
typedef struct {
char *name; // suggest const char *name
void (*func)(); // no parameter info nor checking
} command_info;
char buf[100];
// void setbuf(FILE * restrict stream, char * restrict buf);
command_info fred = { "my_setbuf", setbuf };
// Both compile, 2nd is UB.
fred.func(stdin, buf); // No parameter checking.
fred.func(0); // No parameter checking.
Code also incurs a subtle issue when calling .funf(): the parameters ranking lower than int/unsigned are promoted as well as float parameters before passed to the function. Best to make certain the parameters are not char, float, short, _Bool etc. to avoid compatible signature issues.
void * is a universal object pointer. It may be insufficient to encode a function pointer. So it is not a portable candidate. It is not uncommon for the size of a function pointer to be wider than sizeof(void*).

Is main with parameter list of void different from main with an empty parameter list? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why is the type of the main function in C and c++ left to the user to define?
What is a void ? Anyone provide some examples, proper use of void ? And what is the difference when we write void main (void) or main() ?
In C, in general, (void) means no arguments required in function call, while () means unspecified number of arguments.
e.g.
void foo(void)
{
// body
}
void bar()
{
//body
}
In calling enviroment,
foo(); // Correct
foo(1); // Incorrect
bar(); // Correct
bar(1); // Also correct
This was the general explanation.
But for your case for main() , C99 Standard says that,
5.1.2.2.1 Program startup
The function called at program startup is named main. The
implementation declares no prototype for this function. It shall be
defined with a return type of int and with no parameters:
int main(void) { /* ... */ }
or
with two parameters (referred to here as argc and argv, though any
names may be used, as they are local to the function in which they are
declared):
int main(int argc, char *argv[]) { /* ... */ } or equivalent;
or
in some other implementation-defined manner.
So, in this void main(void) return type should be int.
And at last , for main(),
return type is not given so implicitly return type would be int.
Excluding the return type of the main as in
main(){
}
doesn't mean that it's a void type, it depends on the compiler. I think it can be said it's generically interpreted as
int main(){
}
The void type tells the compiler that there is no 'entity' (no 'storage'), so
void func(int i)
takes an int but returns nothing. In the case of parameters this:
void func()
is equivalent to this:
void func(void)
which indicates more explicitly that it does not take parameters.
Different story is with the type void * which is a type, a pointer to something dimensionless.
Basically, void is a data type, which basically used with method declaration. It means nothing or no type. Eg:
1) int myFunc(void) -- the function takes nothing.
2) void myFunc(int) -- the function returns nothing
3) void* data; -- 'data' is a pointer to data of unknown type, and cannot be dereferenced
Void means "emptyness". In your example of void main() it means that the functions main() does not return a value. I feel obliged tell you that void main() should be avoided (no pun intended) at all costs, use int main() instead. int main() makes sure your program can return a value of type int to the OS on close. There are numerous other uses of void, check out this website if you want to read more about this.
void is a data type with no values. It is also an incomplete data type that cannot be completed. When used as a return type for a function, it indicates that the function does not return a value:
void foo(int x);
When used as a parameter list, it indicates that the function takes no arguments:
void bar(void);
This is different from an empty parameter list, which indicates that the function takes an unspecified number of arguments (in C; in C++, an empty parameter list is the same as using void):
void bletch();
No object (variable) can be typed void. However, you can declare pointers of type void *: these are "generic" pointers, and can be converted to and from other pointer types without an explicit cast. The standard memory allocation functions malloc, calloc, and realloc all return void *:
double *darr = malloc(sizeof *darr * rows);
In a hosted implementation (basically, anything with an operating system), main must be declared as
int main(void)
or
int main(int argc, char **argv) // the parameter names can be whatever you want,
// but argc and argv are the usual convention;
// char **argv is equivalent to char *argv[]
or in some other implementation-defined manner; an implementation may accept
void main()
as a legitimate signature for main, but it must explicitly document that somewhere.

How to define an array of function pointers and the functions don't have same input argument definition?

Is it possible to define an array of function pointers (and the functions don't have se same input argument ) as indicating in the following code ?
If yes what I have to put in the function definition int (*handler)(/*what Ihave to put here ?*/);
struct handler_index {
const char *name;
int (*handler)(/*what Ihave to put here ?*/);
};
int handler0 (int a, int b)
{
printf("%d\n",a+b);
}
int handler1 (int a, int b, int c)
{
printf("%d\n",a+b+c);
}
int handler2 (int a, int b, int c, int d)
{
printf("%d\n",a+b+c+d);
}
const struct handler_index handler_index[] = {
[0] = {"handler0", handler0},
[1] = {"handler1", handler1},
[2] = {"handler2", handler3},
};
Just put nothing:
int (*handler)();
it means the function has an unspecified (but non-variable) number and types of parameters.
Any function that returns an int and with a fixed variable number of parameters can be assigned to handler.
Whilst int (*handler)() will indeed allow variable number of arguments for th function, I fail to see any benefit in this. Function pointers are useful when you have a piece of code that takes something, finds the "right thing to do" (e.g comparing the "name" with some input from elsewhere), and calls the function pointer to do whatever it has to do. The function pointer calling code needs to know how many arguments the function has (how else would it pass the right number and order of arguments.
I don't actually see any meaningful use of this at all. Yes, you can pass a variable number of arguments to a function, but the code HAS to know what arguments the function takes.
Unless the arguments are somehow specified in the definition of the struct - but then you need to define different content for the struct to allow for that.
I would suggest that you need to think about what you are trying to achieve, and then come up with a solution to the problem, most likely using a different method.
Put nothing. Just empty brackets.
int (*handler)();

Can I pass functions as parameter and the function can hold different arguments?

Currently I call function in this way:
typedef struct OptionValueStruct{
const char *option_name;
int (*func)(char*, char**);
} OptionValueStruct_t;
int parse2parameter(char *opt_name, char** opt_val);
int parse3parameter(char *opt_name, char** opt_val, int a);
const OptionValueStruct_t option_values[] = {
{"Counter1", parse2parameter}
};
where parse2parameter is a func() having 2 parameters which is defined in OptionValueStruct_t.
How is it possible I use
const OptionValueStruct_t option_values[] = {
{"Counter1", parse2parameter},
{"Counter2", parse3parameter}
};
Where parse2parameter() and parse3parameter() has different number/type of parameters?
What are you really trying to do, and why?
Think about the code where you receive the function pointer. How are you going to know how to call it?
Look at va_start, va_arg, va_end. You will not be limited by two and three arguments.
You can just use int(*)(), and have some other parameter(s) that describe the function signature so that you can call it. For example:
typedef struct OptionValueStruct{
const char *option_name;
int (*func)(); /* actually takes some arguments */
unsigned num_args; /* might need more fields to describe the args */
} OptionValueStruct_t;
...
switch (value.num_args){
case 2: ((int (*)(char*, char**))value.func)(opt_name, opt_val);
case 3: ((int (*)(char*, char**, int))value.func)(opt_name, opt_val, a);
}
Another way would be to just declare the pointer func to match parse3parameter, and then always call it as if it took three arguments, and (on some platforms), the third argument will simply be ignored. This is probably not portable though.

Passing parameters dynamically to variadic functions

I was wondering if there was any way to pass parameters dynamically to variadic functions. i.e. If I have a function
int some_function (int a, int b, ...){/*blah*/}
and I am accepting a bunch of values from the user, I want some way of passing those values into the function:
some_function (a,b, val1,val2,...,valn)
I don't want to write different versions of all these functions, but I suspect there is no other option?
Variadic functions use a calling convention where the caller is responsible for popping the function parameters from the stack, so yes, it is possible to do this dynamically. It's not standardized in C, and normally would require some assembly to manually push the desired parameters, and invoke the variadic function correctly.
The cdecl calling convention requires that the arguments be pushed in the correct order, and after the call, the bytes pushed as arguments before the call are popped. In this way, the called function can receive an arbitrary number of parameters, as the caller will handle reverting the stack pointer to it's pre-call state. The space occupied by the arguments before the ... is the safe lower bound for number of bytes pushed. Additional variadic arguments are interpreted at runtime.
FFCALL is a library which provides wrappers for passing parameters dynamically to variadic functions. The group of functions you're interested in is avcall. Here's an example calling the functions you gave above:
#include <avcall.h>
av_alist argList;
int retVal;
av_start_int(argList, some_function, retval);
av_int(argList, a);
av_int(argList, b);
av_type(argList, val1);
...
av_type(argList, valn);
av_call(argList);
You might also find this link discussing generating wrappers around variadic functions in C, to be of interest in justifying why this isn't part of standard C.
A standard approach is to have each variadic function accompanied by a va_list-taking counterpart (as in printf and vprintf). The variadic version just converts ... to a va_list (using macros from stdarg.h) and calls its va_list-taking sister, which does actual work.
It might be interesting to try just passing an array, and then use the vararg macros anyway. Depending on stack alignment, it might Just Work (tm).
This is probably not an optimal solution, I mainly posted it because I found the idea interesting.
After trying it out, this approach worked on my linux x86, but not on x86-64 - it can probably be improved. This method will depend on stack alignment, struct alignment and probably more.
void varprint(int count, ...)
{
va_list ap;
int32_t i;
va_start(ap, count);
while(count-- ) {
i = va_arg(ap, int32_t);
printf("Argument: %d\n", i);
}
va_end(ap);
}
struct intstack
{
int32_t pos[99];
};
int main(int argc, char** argv)
{
struct intstack *args = malloc(sizeof(struct intstack));
args->pos[0] = 1;
args->pos[1] = 2;
args->pos[2] = 3;
args->pos[3] = 4;
args->pos[4] = 5;
varprint(5, *args);
return 0;
}
Depending on what it is you're passing around, it could be a discriminated union you're after here (as hinted at in the comments). That would avoid the need for variadic functions or arrays of void*, and answers the question "how does some_function know what you actually passed it". You might have code something like this:
enum thing_code { INTEGER, DOUBLE, LONG };
struct thing
{
enum thing_code code;
union
{
int a;
double b;
long c;
};
};
void some_function(size_t n_things, struct thing *things)
{
/* ... for each thing ... */
switch(things[i].code)
{
case INTEGER:
/* ... */
}
}
You can take this a step further and avoid the switch by replacing the code with one or more pointers to functions that do something useful with each thing. For example, if what you wanted to do was to simply print out each thing, you could have this:
struct thing
{
void (*print)(struct thing*);
union
{
...
};
}
void some_function(size_t n_things, struct thing *things)
{
/* .. for each thing .. */
things[i]->print(things[i]);
/* ... */
}

Resources