What does "..." mean in a C function declaration? - c

What does this mean?
void message(int x, int y, ...)
I can't understand what ... is.
Can anybody explain?

... denotes a variable list of arguments that can be accessed through va_arg, va_end and va_start.

Unspecified/variable number of parameters. To handle such function you have to use the va_list type and va_start, va_arg, and va_end functions:
An example taken from here:
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
int maxof(int, ...) ;
void f(void);
main(){
f();
exit(EXIT SUCCESS);
}
int maxof(int n args, ...){
register int i;
int max, a;
va_list ap;
va_start(ap, n args);
max = va_arg(ap, int);
for(i = 2; i <= n_args; i++) {
if((a = va_arg(ap, int)) > max)
max = a;
}
va_end(ap);
return max;
}
void f(void) {
int i = 5;
int j[256];
j[42] = 24;
printf("%d\n",maxof(3, i, j[42], 0));
}
You can find more details here

You have defined a function message somewhere that takes at least two arguments of type int and then some optional arguments indicated by the "...". (printf is another function taking optional arguments).
The optional arguments can be accessed using the va_* functions.

... represents final argument passed as an array or as a sequence of arguments.

It's the variable argument formal parameter. From the syntactical prospective it allows you pass a variable number of parameters (at least two, which are x and y, but even more).

Related

How to put a function as an argument with unspecified sub arguments in C?

I am trying to make a function, which will execute a function with the provided sub arguments in C. Like:
int function(void (*func)(), ...) // add as many arguments you want for 'func()'
{
va_list ptr;
...
func(sub_arguments) // the '...'
}
void *abc(int a) { ... }
void *one(int b, int c) { ... }
int main()
{
function(abc, 73);
function(one, 9, 84);
}
Now, is there a way to somehow make a variable list and add it as the arguments and execute it? If so, how?
I know I phrased the question in a very difficult way, but I just don't get how to do this.
You can either extract each argument in function() and make the relevant call:
#include <stdio.h>
#include <stdarg.h>
void abc(int a) {
printf("abc(%d)\n", a);
}
void one(int b, int c) {
printf("one(%d,%d)\n", b, c);
}
int function(void (*func)(), ...) {
va_list ap;
va_start(ap, func);
if(func == abc) {
int a = va_arg(ap, int);
func(a);
} else if(func == one) {
int b = va_arg(ap, int);
int c = va_arg(ap, int);
func(b, c);
}
va_end(ap);
return 0;
}
int main() {
function(abc, 73);
function(one, 9, 84);
}
Or change your sub-functions to take a va_list, then pass it from function to the sub-function. That is probably the approach I would would take. If want to call your sub-functions directly that write a wrapper for each that accepts a ... argument (like printf() and vpritnf() pair). Note that this requires the sub-functions to have a fixed argument like function() has func.
One option could be to not use a variadic function at all but to use a C11 _Generic selection to call an implementation of function exactly matching the arguments it's supposed to relay on to func.
With this solution you'll get compile time checks that you've supplied compatible arguments instead of getting undefined behavior during runtime if you've made mistakes when supplying the arguments.
#include <stdio.h>
int function_impl_1(void(*func)(int), int a) {
func(a);
return 0;
}
int function_impl_2(void(*func)(int, int), int a, int b) {
func(a, b);
return 0;
}
#define function(X, ...) _Generic((X), \
void(*)(int): function_impl_1, \
void(*)(int, int): function_impl_2 \
)(X, __VA_ARGS__)
void abc(int a) {
printf("abc(%d)\n", a);
}
void one(int b, int c) {
printf("one(%d,%d)\n", b, c);
}
void two(int b, int c) {
printf("two(%d,%d)\n", b, c);
}
int main(void) {
function(abc, 73);
function(one, 9, 84);
function(two, 123, 456);
}
Demo
Variadic macros with zero variadic arguments are problematic. There's a GNU extension, __VA_OPT__ (from C++20), that can be used for that:
#define function(X, ...) _Generic((X), \
void(*)(void): function_impl_0, \
void(*)(int): function_impl_1, \
void(*)(int, int): function_impl_2 \
)((X) __VA_OPT__(,) __VA_ARGS__)
void zero(void) {
puts("zero()");
}
// ...
function(zero);
Demo

How to pass ellipsis argument to makecontext, which also accepts ellipsis argument in C?

I have a function that runs other functions, and these functions can have a variable number of arguments.
The parameter of this function is then passed to makecontext, which attaches the function to a ucontext_t structure, but the problem is this function also takes variable number of arguments.
So my question is, how do I pass ellipsis argument obtained from a function to makecontext given that I can't change makecontext?
void run_function(void (*func), int argc, ...) {
va_list vl;
va_start(vl, argc);
makecontext(&ucontext, argc, ...);
va_end(vl);
}
As pointed out in the comments by #nemequ, with a compiler like gcc, it is possible to use a variadic macro. But
The va_start() macro needs at least one parameter before the variable number of parameters: the last parameter is the name of the last argument before the variable argument list;
The function func() passed to makecontext() is passed the variable number of parameters but not the argc parameter when it is called.
Hence, the macro wrapper forces argc as first parameter for func() to make it use va_start():
#include <ucontext.h>
#include <stdio.h>
#include <stdarg.h>
#define run_function(ucp, func, argc, ...) \
makecontext(ucp, func, (argc) + 1, argc, ##__VA_ARGS__)
typedef void (* ucfunc_t)(void);
void func1(int argc, ...)
{
va_list ap;
int param;
int i;
va_start(ap, argc);
printf("func1() running with %d parameters:\n", argc);
for (i = 0; i < argc; i ++) {
param = va_arg(ap, int);
printf("\t%d\n", param);
}
va_end(ap);
}
int main(void)
{
ucontext_t main_uc, uc1, uc2, uc3;
char stack1[4096], stack2[4096], stack3[4096];
getcontext(&uc1);
uc1.uc_link = &main_uc;
uc1.uc_stack.ss_sp = stack1;
uc1.uc_stack.ss_size = sizeof(stack1);
getcontext(&uc2);
uc2.uc_link = &uc1;
uc2.uc_stack.ss_sp = stack2;
uc2.uc_stack.ss_size = sizeof(stack2);
getcontext(&uc3);
uc3.uc_link = &uc2;
uc3.uc_stack.ss_sp = stack3;
uc3.uc_stack.ss_size = sizeof(stack3);
run_function(&uc1, (ucfunc_t)func1, 0);
run_function(&uc2, (ucfunc_t)func1, 5, 1, 2, 3, 4, 5);
run_function(&uc3, (ucfunc_t)func1, 2, 1, 2);
getcontext(&main_uc);
main_uc.uc_link = NULL;
swapcontext(&main_uc, &uc3);
return 0;
}
The previous example gives:
$ gcc ex1.c -o ex1
$ ./ex1
func1() running with 2 parameters:
1
2
func1() running with 5 parameters:
1
2
3
4
5
func1() running with 0 parameters:

Couldn't implement function with variable arguments

I was trying to implement function with variable arguments but was getting garbage values as output.I have referred this article before trying to implement on my own.Could anyone help me out with this code as I am unable to understand what's wrong in this code.
/* va_arg example */
#include <stdio.h> /* printf */
int FindMax (int n, ...)
{
int i,val,largest,*p;
p=&n;
p+=sizeof(int);
largest=*p;
for (i=1;i<n-2;i++)
{
p+=sizeof(int);
val=*p;
largest=(largest>val)?largest:val;
}
return largest;
}
int main ()
{
int m;
m= FindMax (7,702,422,631,834,892,104,772);
printf ("The largest value is: %d\n",m);
return 0;
}
The problem is that you try to access locations on the stack directly where you assume to find your arguments. Calling conventions are machine- and sometimes compiler-specific and an implementation detail you can never rely on, so probably your arguments are not found on the stack where you assume they are. In terms of C, your code just invokes undefined behavior
Solution: use stdarg.h for accessing the arguments, that's what it's there for.
#include <stdio.h> /* printf */
#include <stdarg.h>
int FindMax (int n, ...)
{
va_list ap;
int i,val,largest;
va_start(ap, n); // <- ap is the argument pointer, this initializes it
// based on the last non-variadic argument.
largest=0;
while (n--)
{
val = va_arg(ap, int); // <- fetch argument and advance pointer
largest=(largest>val)?largest:val;
}
va_end(ap); // done with argument pointer
return largest;
}
int main ()
{
int m;
m= FindMax (7,702,422,631,834,892,104,772);
printf ("The largest value is: %d\n",m);
return 0;
}

Passing function pointer as an argument using va_args

I am trying to pass a function pointer as part of a number of arguments under va_arg. I tried using a void * wildcard, before typecasting it later, but that gives an error.
fn_ptr = va_arg(*app, (void*));
How does one pass a function pointer, as an argument to another function using va_args?
Just pass the type of the function pointer to va_arg. For example:
#include <stdio.h>
#include <stdarg.h>
void foo()
{
printf("foo\n");
}
typedef void(*foo_ptr)();
void bar(unsigned count, ...)
{
va_list args;
va_start(args, count);
unsigned i = 0;
for (; i < count; ++i) {
foo_ptr p = va_arg(args, foo_ptr);
(*p)();
}
va_end(args);
}
int main()
{
bar(2, &foo, &foo);
}
Live demo

Passing va_list to multi functions without invoke va_arg

I need to implement this code as follows:
#include<stdarg.h>
#include<stdio.h>
typedef struct desc{
void (*function)(void*) //Function address
int no_arg; // Number of arguments
va_list arg; //arguments list
} desc;
desc* creater(void(*func)(), int no_arg1,...){
desc *new_desc;
va_list arg1;
new_desc = (desc*)malloc(sizeof(struct desc));
new_desc->function = func;
new_desc->no_arg = no_arg1;
va_start(arg1 , no_arg1);
va_copy(new_desc->arg,arg1);
va_end(arg1);
}
void start(void(*func)(), va_list varg){
func(&varg);
}
void strat_work(struct desc *desc1){
start( desc1->function,desc1->arg);
}
int test_func(int x, int y){
printf(" The value is =",x + y);
}
int main(void){
desc *desc2;
desc = creater(test_func, 2, 1, 3);
start_work(&desc);
return 0;
}
Could anyone shed light on this implementation? I can see an answer fuzzily also it accepted just one argument.
Thanks in Advance.
Once creator() has returned, the va_list variable and all variable arguments it points to are invalid. You have to extract those arguments before creator() returns. I'm afraid you have to use va_arg().

Resources