How to use Variable Argument Lists without using operator - c

I'm looking for a way to be able to use Variable Argument list without the need to use operator
Code example:
void list_test(int index, ...) {
va_list va;
va_start(va, index);
if (isInt()) {
int *var = va_arg(va, int*);
*var = GetNumber(index);
}
else if (isBool()) {
bool* var = va_arg(va, bool*);
*var = GetEnable(index);
}
va_end(va);
}
So I use it as follows:
list_test(0, &var_int, &var_bool);
Is there a way to do this without using the & operator?
Would it be possible to use va_copy?

Your issue has nothing to do with variadic arguments.
All arguments in C are pass by value, so if you want a function to modify a variable from the calling function, you have to pass that variable's address to the function.
So list_test needs to take pointers as arguments to modify what the pointers point to, whether those arguments are variadic or not.

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.

Why do function pointers exist as long as they act similar to functions themselves?

I know that there is a similar topic, but those answers don't clarify what I want to find out. Thus, as long as from the excerpt below one can notice that a function and the reference to that function behave in the same way, what is the point in having both function variable and function pointers.
#include <stdio.h>
int f(){ return 0;}
int main() {
printf("%p\n",f);
printf("%p\n",&f);
printf("%p\n",f + 1);
printf("%p\n",&f + 1);
return 0;
}
Also, both f and &f could be passed as parameters for other functions.
f and &f mean the same thing, so there's no need to use &f.
But the language designers decided not to make it invalid for some reason, so you have this redundant syntax.
There is no such thing as a "function variable".
A function "decays" into a pointer to a function whenever used in an expression. The only exception to that rule is when it is used together with the & operator in an expression. Then it does not decay but gives the function address in the form of a function pointer.
Therefore f and &f are both identical function pointers in your printf statement. As for the rationale why, it's probably just to keep them consistent with the behavior of arrays, which also decay using similar rules. array vs &array also give the same address.
As for why arrays decay to pointers in the first place, that's just how the language was designed. Dennis Ritchie who invented C didn't want to store addreses or sizes together with arrays (as was done in the ancient predecessor B language) and therefore he came up with this way instead.
f + 1 is pointer arithmetic on a function pointer and doesn't make any sense, like your compiler told you when it refused to compile the posted code.
There are historical reasons for the somewhat weird behavior of the unary & and unary * operators on functions and function pointers, and it is all to do with adding convenience while retaining backwards compatibility for old code.
Prior to the standardization of the C language, it was necessary to apply the & operator to a function to convert it to a function pointer, and it was necessary to apply the * operator to a function pointer in order to to convert it to something of the corresponding function type that can be called. For example:
/* K&R style function pointer example. */
int func(); /* external function declaration */
int foo()
{
int (*fp)(); /* function pointer variable */
int val;
fp = &func; /* assign address of function func to function pointer fp */
val = (*fp)(42); /* dereference and call function pointer fp */
return val;
}
On standardization of the C language, the "function call" operation ( params... ) no longer operates on a function, it operates on a function pointer. However, because it would be inconvenient to apply the & operator to a function to convert it to a function pointer that can be called (i.e. calling a function func as (&func)(42) would be inconvenient), an expression of function type (such as the identifier from a function declaration) is automatically converted to a function pointer value that can be called (i.e. as func(42)), except when it is the operand of the unary &, sizeof or _Alignof operators. This means that a function pointer variable such as int (*fp)(int); can be called directly as fp(42). It also means that for a function func, the expressions func and (&func) are equivalent.
Another example of an expression of function type (the standard defines the term function designator to mean an expression of function type) results from applying the unary * operator or the array subscripting operator [ index ] to a function pointer. This means that the old, pre-standard way of calling a function pointed to by a function pointer variable still works the same as it always did. For example, in the call (*fp)(42), the function pointer value of fp is converted by the unary * operator to an expression of function type, but the expression of function type (a function designator) is automatically converted back to an expression of function pointer type. This means that all the following (and similar) ways of calling a function func are effectively equivalent:
func(42);
(&func)(42);
(*func)(42);
func[0](42);
(&*&*&*&*&func)(42);
(*&*&*&*&*func)(42);
For a function pointer variable fp the following and similar ways of calling the function are effectively equivalent:
fp(42);
(*fp)(42);
(&*fp)(42);
fp[0](42);
(*&*&*&*&*fp)(42);
Note that (&fp)(42) for function pointer variable fp is not a valid function call because &fp is a pointer to a function pointer and the function call operation only works on function pointers.
For standard C, the previous K&R style function pointer example can be rewritten as the following:
/* New style function pointer example. */
int func(int); /* external function declaration */
int foo(void)
{
int (*fp)(int); /* function pointer variable */
int val;
fp = func; /* assign pointer to function func to function pointer fp */
val = fp(42); /* call function pointer fp */
return val;
}
As to the point of having variables (or parameters) of function pointer type, they have their uses as others have pointed out.
Function pointers are necessary when you want a variable to refer to a particular function. For example:
#include <stdio.h>
void foo1(void)
{
printf("foo1\n");
}
void foo2(void)
{
printf("foo2\n");
}
int main()
{
void (*f)(void) = foo1;
f();
f = foo2;
f();
return 0;
}
Output:
foo1
foo2
If you attempted to do this:
void f(void) = foo1;
It would be invalid syntax. And if you removed the initializer:
void f(void);
You would have a function declaration.
As others have pointed out: &f and f are the same thing: when assigning f, or passing it as an argument, much like an array, the value you're passing/assigning is the address of (pointer to) the function.
If the question you're asking is "Why are there function pointers", then you might want to consider this:
Say you're writing a library like GTK. You'll want the users of said library to be able to handle stuff like a button being clicked. This is done by allowing the user to pass in a function pointer. The pointer will point to the function they want to be called when a button is clicked. Simplest example: A GTK window with a button to quit the application:
g_signal_connect(
G_OBJECT(close_button),
"clicked",
G_CCALLBACK(close_window_cb),
G_OBJECT(sub_window));
I'm basically telling GTK that, if a the object close_button is clicked, there's a callback function I want to have called. This callback is passed in as a function pointer. I'm also telling GTK to pass a pointer to sub_window as the second argument, so my function can close the window (destroy the widget).
The callback itself is very simple, and looks like this:
void close_window_cb(GtkWidget *w, gpointer window)
{
gtk_widget_destroy(GTK_WIDGET(window));
}
You may think it'd be easier to just bind gtk_widget_destroy to the event, but what if I want to log something, or perform some other actions?
void close_window_cb(GtkWidget *w, gpointer window)
{
printf("Button %s was clicked", gtk_widget_get_name(w));
gtk_widget_destroy(GTK_WIDGET(window));
}
Without supporting user-defined callback functions, that'd be a hassle to implement.
TL;DR
You don't need function pointers, but they are quite useful in quite a lot of situations.
A function pointer is a variable that refers to a function. The concept is useful in a number of scenarios. C is statically linked, every regular function call is resolved to a fixed address assigned by the linker. Function pointers allow decisions about which function will be called to be made at run-time.
Some examples:
The standard library qsort() uses a function pointer to enable it to operate on arbitrary object types rather then requiring a separate function for every type of object you might want to sort.
Interrupt handlers can be function pointers-written to the interrupt vector table, allowing you to dynamically install a n interrupt handler at run-time.
It can simplify command parsers or menu handlers by replacing large switch-case or if-else if-else constructs with a look-up table or associative map.
Event handlers. For example a library may generate an event that requires a user defined handler written independently of the library. The POSIX signal() function for example.
I agree that the & operator on a function designator is redundant, as f and &f evaluate to the same value and type (unlike arrays). I suspect it's there more for consistency's sake than anything else.
Function pointers themselves have a number of uses.
They allow you to pass a function as an argument to another function for that function to execute (a.k.a. a callback). The canonical example is the standard library function qsort:
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
qsort calls the function pointed to by compar to determine how to order the elements of the array. You can change the ordering just by passing different callbacks.
The few C-based GUI frameworks I have experience with had callbacks out the wazoo.
Function pointers allow you to add functionality to your application at runtime by loading a shared library:
#include <dlfcn.h>
...
void *libhandle = dlopen( "libfoo.so", RTLD_LAZY | RTLD_GLOBAL );
...
int (*do_something)(void) = dlsym( libhandle, "some_function_name" );
if ( do_something )
{
int x = do_something();
...
}
They allow you to attach a behavior to an object - for example, I can attach a comparison function to a list object that allows me to control the ordering of the list (similar to passing the compar function to qsort):
struct node {
data_t data; // for some arbitrary data type
struct node *next;
};
struct list {
struct node *head;
int (*compar)( const data_t, const data_t );
};
...
void insert( struct list *l, data_t value )
{
struct node *new = new_node( value ); // allocates node and assigns data
struct node *cur = l->head, *prev = NULL;
while ( l->compar( cur->data, new->data ) <= 0 )
{
prev = cur;
cur = cur->next;
}
new->next = cur;
if ( prev )
{
prev->next = new;
}
else
{
l->head = new;
}
}
So I can create two lists:
struct list a, b;
that I can order different ways by attaching different comparison functions:
int sort_ascending( const data_t a, const data_t b )
{
...
}
int sort_descending( const data_t a, const data_t b )
{
...
}
a.compar = sort_ascending;
b.compar = sort_descending;
You can build lookup tables that can execute a function based on one or more criteria, and adding new functionality is just a matter of writing the new functions and adding them to the table, rather than hacking the application logic itself:
void (*do_something[])( void ) = { do_A, do_B, do_C };
...
int x = get_some_value();
do_something[x]();

C generic Parameter into Function pointer

Is it possible in C(not C++) to have a fuction pointer that takes a generic value(not a pointer), with -pedantic and -wall -werror flags set.
Note: I can't change the parameter Type. The code has to support uint8_t, uint16_t, etc... types as the parameters
Goal: to solve the problem with code.
Question
Is there a way to typecast a uint8_t(and/or uint16_t) parameter to a void*(Approach1)?
specifically to pass a non-pointer type value to a void* value.
Is there a way to setup a Generic Type that will work with all the different values(Approach 2)?
Last resort
Is there a way to set a specific compiler Exception in the code?(this question has been answer)
Approach 1(causes a invalid conversion from uint8_t to void*)
typedef struct
{
void (*set_func)(void*);
} SetFunction;
void setValue(uint8_t byteValue)//Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue)//Not a pointer parameter
{
byteValue++;
}
int main()
{
uint8_t a = 123;
uint16_t b = 321;
SetFunction pointerFuncion;
SetFunction pointerFuncionShort;
//Typecast the setValue to appease compiler warning
pointerFunction.set_func = (void(*)(void*))&setValue;
pointerFuncionShort.set_func = (void(*)(void*))&setShortValue;
//use the function pointer with non-pointer parameter
// Compile ERROR thrown invalid conversion from uint8_t to void*
pointerFunction.set_func(a);
pointerFuncionShort.set_func(b);
}
Aprroach 2(causes a Too Many Parameters Compile Error)
typedef struct
{
void (*set_func)();//Blank parameter to allow multiple args
} SetFunction;
void setValue(uint8_t byteValue)//Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue)//Not a pointer parameter
{
byteValue++;
}
int main()
{
uint8_t a = 123;
uint16_t b = 321;
SetFunction pointerFuncion;
SetFunction pointerFuncionShort;
//Typecast the setValue to appease compiler warning
pointerFunction.set_func = (void(*)())&setValue;
pointerFuncionShort.set_func = (void(*)())&setShortValue;
//use the function pointer with non-pointer parameter
pointerFunction.set_func(a);// Compile ERROR thrown "Too many Args"
pointerFuncionShort.set_func(b);// Compile ERROR thrown "Too many Args"
}
UPDATE
To add clarity to the problem.
I have 100's of functions with 1 parameter.
The 1 parameter of the functions are different types.
I can't change any of the functions, but I want to have 1 function pointer type(or more based on type) to any of the functions.
I can change any of the types associated with the function pointer and the type to the function pointer, but not what it is pointing too.
No, it is not.
Simple answer: The called function does not know how to even fetch the argument.
Details: The function code is already fixed when it is called (executed). So it contains code to access the argument, which depends on the type of the arguemtn (e.g. for an uint32_t, a 32 bit load/soter is required, for an uint8_t an 8 bit load/store). So it cannot handle even the value fetch properly.
Different from C++ and higher languages like Python, C does not have a concept of run-time type identification built-in.
However, you can pass a union to the function and handle each variant in the function seperately. That would generate all possible accesses. However, you have to specify which actual type is being passed. This is normally done by a second argument which specifies the actual type.
That union could also be a struct composed of the type-identifier and the actual value. But that is just an envelope, everything is still explicit.
typedef union {
int i;
float f;
} MyValue;
typedef enum {
MY_VALUE_int,
MY_VALUE_float
} MyValueType;
void func(MyValueType type, MyValue value)
{
switch ( type ) {
...
}
}
int main(void)
{
func(MY_VALUE_int, (MyValueType){ .i=1 });
}
The compound literal argument only works for constants, otherwise you have to assign the value to a union first (or just use that union).
gcc has an extension to avoid this, so you can have a function which takes such a union, but the caller may use a simple cast, instead of a compound literal. That works for variables, too:
func(MY_VALUE_float, (MyValueType)1.0);
An alternative would be passing a const void * and internally casting. However, that is even more risky than the union approach.
All approaches require pasing the actual type explicitly (e.g. using an enum).
C11 allows to create a macro which evaluates different expressions, according to the type of an argument using the new _Generic construct. With that the original approach can be simulated (using gcc extension, normal way is possible, but more complicated):
// use the code of the first block here
#define func_generic(val) _Generic((val), \
int : func(MY_VALUE_int, (MyValueType)(val)), \
int : func(MY_VALUE_int, (MyValueType)(val)) )
// and call like:
func_generic(1);
func_generic(1.0);
However, note the restriction of _Generic: No two compatible types are allowed for the type-selector (i.e. const int and int are not allowed both) for uint16_t and uint32_t this works, however.
Note that gcc (you apparently use) supports C11 using -std=c11 or std=gnu11. The latter also enables GNU-extensions.
The short answer is no.
You have several problems:
1) The different functions all have to have the same signature to allow the function pointer to point to them.
2) The functions are taking their args by value which means a copy will be passed in and any actions you take on the value will not appear to have any affect outside the function call. Since you don't allow pointers I cant see any way round this.
If you are not bothered about problem 2 then you could try declaring a variadic function which will accept args of any type.
e.g.
void doSomethingWithValue(enum MyType type ...)
{
va_list args;
va_start( args, type);
switch( type)
{
case Uint8Type:
{
uint8_t value = va_arg(args, uint8_t);
//doSomething to value
}
break;
.
.
.
}
va_end(args);
}
Where MyType is an enum set up to identify which type is passed in.
which is used like so:
uint8_t value = 7;
doSomethingWithValue(Uint8Type, value);
//note that value is still 7
Note that both of your exampels exibit Undefined Behaviour because you call a function through a pointer of another (function) type.
I found a solution that relies on the fact that there are a limited number of function types known in advance. I think however that it is too much hassle. Just call the original function.
enum GFType {
GF_UINT8,
GF_UINT16 // etc
};
struct GenericFunction {
void (*func)(void);
GFType type;
};
void callGenericFunction(GenericFunction func, uint64_t p) // largest type
{
switch (func.type) {
case GF_UINT8:
((void (*)(uint8_t))func.func)(p);
return;
case GF_UINT16:
((void (*)(uint16_t))func.func)(p);
return;
default:
assert(1); // unimplemented function type
}
}
void setValue(uint8_t byteValue) // Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue) // Not a pointer parameter
{
byteValue++;
}
int main() {
uint8_t a = 123;
uint16_t b = 321;
GenericFunction pointerFunction;
GenericFunction pointerFunctionShort;
pointerFunction.func = (void (*)(void))setValue;
pointerFunction.type = GF_UINT8;
pointerFunctionShort.func = (void (*)(void))setShortValue;
pointerFunction.type = GF_UINT16;
callGenericFunction(pointerFunction, a);
callGenericFunction(pointerFunctionShort, b);
return 1;
}
Note that
a function-pointer may be freely converted to any other
function-pointer type and back again, and you will get the original
pointer.
This is what we use. We can't even use void * (because it is a data pointer, not a function pointer) to store the function pointer. So I used void (*)(void) to store the function pointer. An enum tells us to what kind of function we must convert it when we need to cal it.
If you can use C11, there is a way to do this using _Generic:
#include <stdio.h>
#include <inttypes.h>
#define setvalue_generic(x) _Generic((x), \
uint8_t: setValue, \
uint16_t: setShortValue \
)(x)
void setValue(uint8_t byteValue)
{
printf("setValue: %" PRIu8 "\n", byteValue);
byteValue++;
}
void setShortValue(uint16_t byteValue)
{
printf("setValue: %" PRIu16 "\n", byteValue);
byteValue++;
}
int main(void)
{
uint8_t a = 123;
uint16_t b = 321;
setvalue_generic(a);
setvalue_generic(b);
return 0;
}
Seems to work well with gcc -std=c11 -pedantic -Wextra -Wall.
#bolov answer is good for handling the different types, this is just a different way of handling the same issue, but with 1 parameter.
The downside to this approach is that the type in main has to be GENERAL_TYPE. In my application I can change the type of the parameter, but I can change the type of the functions that I'm pointing to.
the (void(*)(GENERAL_TYPE))& handles the function's parameter types, and the Union handles the types of all the different sizes.
Another option is to have function pointers for each type too.
typedef union generalType
{
uint8_t byteData;
uint16_t shortData;
uint32_t intData;
int integerData;
uint64_t longData;
void * voidData;
//Add any type
} GENERAL_TYPE;
typedef struct
{
void (*set_func)(GENERAL_TYPE);
} SetFunction;
void setValue(uint8_t byteValue)//Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue)//Not a pointer parameter
{
byteValue++;
}
int main()
{
GENERAL_TYPE a.byteData = 123;//restricted to use GENERAL_TYPE here
GENERAL_TYPE b.shortData = 321;
SetFunction pointerFuncion;
SetFunction pointerFuncionShort;
//Typecast the setValue parameter to be a general type will
//Allow it to send the data of whatever type.
pointerFunction.set_func = (void(*)(GENERAL_TYPE))&setValue;
pointerFuncionShort.set_func = (void(*)(GENERAL_TYPE))&setShortValue;
//use the function pointer with non-pointer parameter
pointerFunction.set_func(a);
pointerFuncionShort.set_func(b);
}

Pass a function with undetermined number of arguments and call it with the variadic arguments

I'd like to create a function "lazy" which accepts a function with an undetermined number of arguments as parameter. What type do I need or which casts have to be done?
Then I want to execute that thing later in function "evaluate". How do I then pass the arguments I passed before to the "lazy" function to the passed function pointer?
Some code to illustrate my problem:
char *function_I_want_to_call(void *foo, type bar, ...);
// the arguments are unknown to lazy() and evaluate()
typedef struct {
??? func;
va_list args;
} lazy_fcall;
void lazy(lazy_fcall *result, ??? func, ...) {
// which type do I need here?
va_start(result->_args, fund);
result->func = func;
}
void *evaluate(lazy_fcall *to_evaluate) {
return to_evaluate->func(expand_args(to_evaluate->args));
// what do I have to write there to expand the va_list? It's C, not C++11...
}
int main () {
lazy_fcall lazy_store;
lazy(&lazy_store, function_I_want_to_call, "argument_1", "argument_2");
// ...
printf("%s", (char *)evaluate(&lazy_store));
}
Or is something like this just impossible? Which other possibilities exist?
You can't expand a va_list into separate arguments. The function you want to call have to be able to take a va_list as argument. See e.g. printf versus vprintf.
Also, as noted by caf, you can't store a va_list, as the arguments "pointed" to by it will not be valid once the lazy function returns. Attempting to use the va_list will lead to undefined behavior and all kinds of weirdness.

Standard way to manipulate variadic arguments?

This is a weird question, but is there a standard way to manipulate the contents of a va_list before passing it to another function? For instance, suppose I have two functions, sum and vsum:
int vsum(int n, va_list ap) {
int total = 0;
for (int i = 0; i < n; ++i) {
total += va_arg(n, int);
return total;
}
int sum(int n, ...) {
va_list ap;
va_start(ap, n);
int total = vsum(n, ap);
va_end(ap);
return total;
}
If I call sum as sum(4, 1, 2, 3, 4), I expect to get the result 10. Now let's suppose that instead of calling vsum directly, sum calls an intermediate function, vsum_stub which does the following:
int vsum_stub(int n, va_list ap) {
va_list temp_ap;
va_copy(temp_ap, ap);
for (int i = 0; i < n; ++i) {
int *arg = &va_arg(ap, int);
*arg += 2;
}
va_end(temp_ap);
return vsum(n, ap);
}
Now when I call sum(4, 1, 2, 3, 4), I should get back the result 20, since vsum_stub increments all of the values in the va_list by 2. This doesn't compile of course since you can't take the address of the result of va_arg. Is there another way to do this though? I'm working in C99.
Background:
I'm working on a library that does some pointer translation so that data may be stored on the heap in a more efficient format. Programs are compiled with a custom transformation which converts calls to library functions like printf to my own stub functions (e.g., hc_printf). hc_printf needs to translate any pointer arguments (strings intended for %s) before passing the arguments to the real printf function.
Edit: Here's a code example. Let's say we have a string foo. foo is dynamically allocated with a modified version of malloc which returns a fake pointer. The compiler modifies the program so that it can deal with fake pointers. So this works:
char *foo = fake_malloc(4);
fake_strcpy(foo, "foo");
I want to write a fake_vprintf function like this (in pseudocode):
int fake_vprintf(const char *format, va_list args) {
for each pointer argument p in args
translate p to q, a real pointer to contiguous memory
replace p with q in args
}
return vprintf(format, args);
}
The program would call fake_vprintf just like the original vprintf using the fake pointer. fake_vprintf translates the fake pointer to a real pointer that the real vprintf can use.
Aha, as I understand, your problem is creating a new va_list argument to pass on to the standard vprintf functions. Which in turn, will require you to modify each member of the list. However, since there is no element wise fetch/edit/insert operation for such a list you are stuck.
I don't really see any way of doing this. Of course, you can create a vprintf apply the transformations in situ, one argument at a time. My suggestion will be: Reimplement all such standard library functions -- at any rate you are writing wrappers. This involves some work, but you are already doing a part of it with hc_printf etc, so why not go the whole distance (and guess what save on a function call!).
You probably can't use va_list in a platform-agnostic way. You'll have to look at how your environment defines a va_list in stdarg.h, and then write your own tools to work with it.
For example, if a va_list is just a (char *), you can do all sorts of things with it.
// add 1000 to the integer stored on the stack and advance va_list
*(int *)va_list += 1000;
va_list += sizeof(int);
You're telling the compiler that you want it to consider va_list a pointer to an int (via the int * cast), then take the value (*) and add 1000 to it (+= 1000). Now advance the va_list pointer to the next argument on the stack.

Resources