I did some test code to demonstrate different output on Windows and Linux
#include <stdarg.h>
#include <stdio.h>
void print_vint(va_list args)
{
int i = va_arg(args, int);
printf("%dn", i);
}
void variadic_f(const char* format, ...)
{
va_list args;
va_start(args, format);
print_vint(args);
print_vint(args);
va_end(args);
}
int main(int argc, char* argv[])
{
variadic_f("dummy ", 1, 2);
return 0;
}
print_vint
function has argument of type va_list
passed by value. On Windows machine it is pointer to stack right after the last nonvariadic parameter. Parameter is passed to function by value and function changes it when invoking va_arg
. Second invocation of print_vint
gets same pointer value (since local copy inside function was changed) and prints same output as first invocation.
Here is Windows output of program invocation:
1
1
I compile same source code on Linux and run. Output is different:
1
2
My conclusion is that Linux uses pointer to opaque structure which has pointer to stack and when va_list is passed by value dereferencing pointer and changing pointer inside structure will be visible in consecutive use of va_list
.
Does the C standard specify how va_arg
should behave and how execution affects va_list
argument?
My goal is to make portable functions which would handle variadic argument as input (`va_list’).