Passing a dynamic set of variadic arguments to a C function [duplicate] - c

This question already has answers here:
In C, given a variable list of arguments, how to build a function call using them?
(4 answers)
Closed 4 years ago.
I'm trying to call a C function that takes variadic arguments, and I need to pass in a dynamic number of arguments to the function. Additionally, this is an API I can't modify without going to a lot of effort, so if there's any possible to make this work I'll take it.
As far as I can tell, va_list is not sufficient for this purpose since you can't pass a va_list where ... was written in the original function signature.
Answers for other questions like this one talk about how to pass a ... from one function to another, but that's not what I'm doing. I need to actually dynamically generate the list of arguments, I'm not getting it in as a .... Also, all the answers I can find rely being able to modify the function to take a va_list, which is not an option here.
There was also this question, which was marked as a dupe of the previous question despite not actually asking the same question. Again, the only answer suggests converting the call to use va_list which is not an option.
I would understand if the standard didn't include a way to do this, but this seems like a case where I can imagine a perfectly reasonable implementation. This isn't so different from, say, alloca. Anyway, if it's not possible, that's fine, but I'd like the SO community to realize that this isn't a dupe of this question and deserves a definitive answer.
The API I'm calling is in C, but if there's a way to do this in C++ I would consider it.
Edit: If you have these requirements, it looks like this answer using libffi is the best way to go. There does not appear to be a way to do this either in standard C or with GCC extensions otherwise.

If you use gcc compiler, you can use __builtin_va_arg_pack() or __builtin_apply(), see here.
Examples:
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
int my_printf(const char *fmt, ...)
{
void *args = __builtin_apply_args();
void *ret = __builtin_apply((void(*)())printf, args, 100);
__builtin_return(ret);
}
extern int my2_printf(const char *, ...);
extern inline __attribute__((__always_inline__,__gnu_inline__))
int my2_printf(const char *fmt, ...) {
return printf(fmt, __builtin_va_arg_pack());
}
int main()
{
my_printf("%s %s %s %s %s\n", "Hi", "I", "am", "kamil", "!");
my2_printf("%s %s %s %s\n", "Variadic", "args", "are", "fun");
return 0;
}
#edit:
As the question is also about on how to construct a dynamic argument list and then pass it to function. You can create a function for each case you need to support and use a big switch to differentiate between them.
A example for printing an array of unknown compile size:
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdlib.h>
#include <boost/preprocessor/repetition/repeat.hpp>
void print_array(size_t cnt, ...)
{
va_list va;
va_start(va, cnt);
printf("%s cnt=%d :", __func__, cnt);
for (size_t i = 0; i < cnt; ++i) {
printf(" %d", va_arg(va, int));
}
va_end(va);
printf("%s\n");
}
// we support an array up to that many arguments
#define CALL_PRINT_ARRAY_MAX 128
#define CALL_PRINT_ARRAY_ARGS(z, n, text) \
, arr[n]
#define CALL_PRINT_ARRAY_DECLARE(z, n, text) \
void call_print_array_##n (int arr[]) \
{ \
print_array(n BOOST_PP_REPEAT(n, CALL_PRINT_ARRAY_ARGS, ())); \
}
BOOST_PP_REPEAT(CALL_PRINT_ARRAY_MAX, CALL_PRINT_ARRAY_DECLARE, ())
#undef CALL_PRINT_ARRAY_DECLARE
#undef CALL_PRINT_ARRAY_ARGS
int call_print_array(int arr[], size_t n)
{
switch(n) {
#define CALL_PRINT_ARRAY_CASE(z, n, text) \
case n: call_print_array_##n(arr); break;
BOOST_PP_REPEAT(CALL_PRINT_ARRAY_MAX, CALL_PRINT_ARRAY_CASE, ())
#undef CALL_PRINT_ARRAY_CASE
default:
fprintf(stderr, "Array size is too big for what we're prepared\n");
return -1;
}
return 0;
}
int main()
{
//int a1[5] = {1,2,3,4,5};
//call_print_array(a1, sizeof(a1)/sizeof(a1[0]));
size_t size;
scanf("%zu", &size); // insecure
int * a2 = calloc(size, sizeof(*a2));
for (size_t i = 0; i < size; ++i)
a2[i] = i;
call_print_array(a2, size);
return 0;
}

The easiest way to do this would be with variadic macros, kind of like the way it's done for eprintf:
#define eprintf(…) fprintf (stderr, __VA_ARGS__)
__VA_ARGS__ expands into the full argument list passed into the macro with which you can then call the other function declared with .... Unfortunately what you want to do cannot be done within a function without going through a lot of effort that you seem to want to avoid.

Related

How to prepend formatted data to an printf() call

I want to implement a variadic function which behaves like printf, except that it prints some prefix. For example, let's say I want the prefix to be the value of time(0). if I call:
wrapped_printf("Hello, world %d", 5678);
I'll expect something like:
1571441246 Hello, world 5678
as the output.
Obviously, replacing the format string is not a big deal; it's the variadic business that's giving me trouble. Should I implement this as a function taking ...? Taking a va_list? And how do I prepend my extra arguments?
This is what I have right now. It compiles and runs (it's valid C89 even...), but the extra arguments get messed up.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
int wrapped_printf(const char* format_str, ...)
{
static const char* const prefix = "%d ";
static const size_t prefix_length = 3;
va_list ap;
size_t format_string_length = strlen(format_str);
char* const prefixed_format_str = malloc(format_string_length + prefix_length + 2);
/* 1 for the trailing '\0' and 1 for a line break */
if (prefixed_format_str == NULL) { exit(EXIT_FAILURE); }
strncpy(prefixed_format_str, prefix, prefix_length);
strncpy(prefixed_format_str + prefix_length, format_str, format_string_length);
prefixed_format_str[prefix_length + format_string_length] = '\n';
prefixed_format_str[prefix_length + format_string_length + 1] = '\0';
va_start(ap, format_str);
return printf(
prefixed_format_str,
(int) time(0),
ap);
va_end(ap);
}
int main()
{
wrapped_printf("Hello world %d\n", 5678);
return EXIT_SUCCESS;
}
See it failing on Coliru.
Notes:
Only one call must be made - but it can be either to printf() or vprintf().
One can use a large string buffer, sprintf() the prefix into it, then sprintf() the original arguments afterwards; but that's also not what I mean.
I don't mind using compiler-specific code - but if you suggest that, please try covering more than a single compiler on more than a single platform - and especially GCC or clang on GNU/Linux with an AMD64 processor.
It is totally not possible to prepend arguments to a va_list portably in plain C. It can be done for sure, but it would require compiler-level wizardry for each architecture and compiler and calling-convention.
For a portable way, a library like libffi and a parser for the format strings...
I suggest that if possible you'd go for a macro instead, if you're lucky enough to be on C99+; then you can prepend "%d " to the format string with compile-time string catenation and add the number in the arguments rather easily. But the format need to be a string literal for this.
Or if you really need to use a function then I don't get the restriction of not using printf separately for the prefix followed by these - the output would be line-buffered or fully-buffered so there would not likely be any difference.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#define wrapped_printf_macro(f_, ...) \
printf("%lld " f_, (long long)time(0), __VA_ARGS__)
int wrapped_printf(const char* format_str, ...)
{
static const char* const prefix = "%d ";
static const size_t prefix_length = 3;
va_list ap;
printf("%lld ", (long long int)time(0));
va_start(ap, format_str);
vprintf(format_str, ap);
va_end(ap);
}
int main()
{
wrapped_printf_macro("Hello world %d\n", 5678);
wrapped_printf("Hello world %d\n", 5678);
return EXIT_SUCCESS;
}

C - passing function with arguments into wrapper executor

Is there a way to build a wrapper function in C as follows:
void wrapper(void *func) {
// Set up
func([same arguments as func was passed in with]);
// Clean up
}
void foo(int x, int y);
void bar(char *z);
wrapper(foo(1, 2));
wrapper(bar("Hello"));
It seems as though you have to either pass in the arugments within wrapper or only support one type of method header for func. I've been writing a lot of Javascript... and of course this is possible in JS.
That's the best I can think of with variadic function wwrappers:
#include <stdio.h>
#include <stdarg.h>
void wrapper(void (*func)(va_list), ...) {
va_list args;
va_start(args, func);
func(args);
va_end(args);
}
void foo(int x, int y)
{
printf("foo(%d,%d)\n", x, y);
}
void vfoo(va_list args)
{
foo(va_arg(args, int), va_arg(args, int));
}
void bar(char *z)
{
printf("bar(%s)\n", z);
}
void vbar(va_list args)
{
bar(va_arg(args, char*));
}
int main()
{
wrapper(vfoo, 1, 2);
wrapper(vbar, "Hello, World!");
return 0;
}
Live example on Coliru.
Have you considered (ab)using the preprocessor?
#include <stdio.h>
#define wrapper(f) /* Set up */\
f; \
/* Clean up */
void foo(int x, int y) {
printf("x: %d; y: %d\n", x, y);
}
void bar(char *str) {
printf("str: %s\n", str);
}
int main(void) {
wrapper(foo(42, 11));
wrapper(bar("hello world"));
}
To elaborate upon why I added the possibility of an ab- prefix to (ab)use, I wouldn't hesitate to use whatever is the most expressive solution to a problem, regardless of the attitude held by the general populus. However, I recognise that sometimes we have no control over the restrictions we are bound by, and policies are often put in place to heavily restrict the use of macros. Unfortunately, those bound by such silly policies won't find this post too helpful.
In a comment above I suggested that "if you want a feature from Javascript you should probably write your code in Javascript...".
Upon pondering about this overnight, I came to the conclusion that features similar to those you ask are actually doable and would be quite nice in C... so I admit, I was wrong.
The following is an example of mimicking how Javascript treats functions.
#include <stdio.h>
struct argument;
typedef struct argument argument;
typedef void function(argument *);
struct argument {
function *function;
/* for foo() */
int x;
int y;
/* for bar() */
char *str;
};
void wrapper(argument *a) {
// set up
a->function(a);
// clean up
}
void foo(argument *a) {
printf("x: %d; y: %d\n", a->x, a->y);
}
void bar(argument *a) {
printf("str: %s\n", a->str);
}
#define foo(...) wrapper(&(argument){ .function = foo, __VA_ARGS__ })
#define bar(...) wrapper(&(argument){ .function = bar, .str = "", __VA_ARGS__ })
int main(void) {
foo(.x = 42, .y = 11);
bar(.str = "hello world");
}
There are actually some really nice features coming from this style of wrapper:
It becomes very difficult for a down-stream programmerr to mung the stack, where-as it is very easy for programmers using typical variadic functions such as printf and scanf to cause subtle yet devastating bugs by passing the wrong types and/or values to those functions. This leads on to my next point:
Default argument values are possible by simply modifying the foo and bar macros. As an example in the code above, the default value for the argument named str is set to "" (an empty string) for bar.
By introducing extra logic into wrapper, you can mimic partial function application (or binding properties to functions, much like you'd see in Javascript). Additionally, with a little bit of effort, mimicking continuation passing style might be possible by turning wrapper into a trampoline-style function and modifying the return value? I'll ponder more on this and provide an update tomorrow.
Finally, down-stream users are encouraged to pair argument identifiers with argument values, which improves maintainability drastically.
There are some minor draw-backs, the most significant being that neither foo nor bar can be passed, unapplied, to another function as an argument. This would be rare for these functions specifically, as they differ greatly in signature, but for functions that are identical or even similar in signature I can understand one might want to pass them as callbacks or what-not.
The solution to that problem is to rename the macros to default_foo and default_bar or something like that...
Finally, thanks for asking such a thought-provoking question... I hope reading my answer has been as interesting for you as thinking about (and writing) it was for me.

Printing only integer arguments in variable argument function in C

I want to write a C function, which can take any number of arguments and print value of int arguments only. I saw va_list and va_arg in stdarg.h, but I couldn't find any mechanism to get the number of arguments. I cannot take first argument as the number of arguments.
There's no portable way in standard C to get the number of arguments in variable argument functions.
The common way to solve it is to use the rightmost parameter parmN to provide the number of integers explicitly. For instance, your function prototype may look like this:
int foo(int number, ...);
But this is not an option to you according to your question.
Reference: C FAQ: How can I discover how many arguments a function was actually called with?
There is no (portable) way to get the number of arguments in a variadic function at runtime. That number is lost at runtime (only the compiler knows it).
Notice that on common processors and application binary interfaces (ABI) convention (e.g. x86-64 ABI on Linux), the machine itself does not know at runtime the arity of the current call in C; this is also true for others x86 calling conventions. However, when the compiler is compiling a variadic call, it does know the arity at compile time (but does not emit it in the object file).
You could define the convention that your variadic function takes as first argument the number of remaining (variadic) arguments:
void print_integers (int nbints, ...);
Then you would implement it e.g.
#include <stdio.h>
#include <stdarg.h>
void print_integers (int nbints, ...)
{
va_list args;
va_start (nbints, args);
for (int ix=0; ix<nbints; ix++) {
int curarg = va_arg(args, int);
printf(" %d", curarg);
};
va_end(args);
fflush(NULL);
}
If you cannot do this, you have to customize your preprocessor or your compiler. Perhaps a job for your MELT extension (MELT is a domain specific language to extend GCC). Or perhaps use GPP as your preprocessor.
You could also play some cpp preprocessor tricks, notably stringification and concatenation and variadic macros. For instance, you might define
void print_integers_str(const char*, ...);
#define print_my_integers(...) \
print_integers_str(#__VA_ARGS__, ##__VA_ARGS__);
Then print_my_integers(x,y) gets expanded to print_integers_str("x,y", x,y) and your varadic function print_integer_str could parse the "x,y" literal string (at least count commas). But with print_my_integers(f(x,y),g(y)+/*,,*/k)you may get a nightmare.
To be short: I recommend give up that goal and do things otherwise.
Using NARGS macro (in this case limited to 8 args):
#include <stdio.h>
#include <stdarg.h>
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define fn(...) fn(NARGS(__VA_ARGS__), __VA_ARGS__)
static void (fn)(int n, ...)
{
va_list args;
int i;
va_start(args, n);
for (i = 0; i < n; i++) {
printf("%d\n", va_arg(args, int));
}
va_end(args);
}
int main(void)
{
fn(6, 7, 8);
return 0;
}
Or you can loop until -1:
#include <stdio.h>
#include <stdarg.h>
#define fn(...) fn(0, __VA_ARGS__, -1)
static void (fn)(int n, ...)
{
va_list args;
int i;
va_start(args, n);
while (1) {
i = va_arg(args, int);
if (i == -1) break;
printf("%d\n", i);
}
va_end(args);
}
int main(void)
{
fn(6, 7, 8);
return 0;
}

C : write a function doesn't know how many parameter

When learning C I see that printf can receive many arguments as it is passed.
And I don't know how C can implement a function like this, where the user can type as many parameters as the user wants. I have thought about pointers, too but still have no bright idea. If anyone has any ideas about this type of function, please tell me.
You need to use va_args, va_list and the like.
Have a look at this tutorial.
http://www.cprogramming.com/tutorial/c/lesson17.html
That should be helpful.
You have to use the ... notation in your function declaration as the last argument.
Please see this tutorial to learn more: http://www.cprogramming.com/tutorial/c/lesson17.html
#include <stdarg.h>
#include <stdio.h>
int add_all(int num,...)
{
va_list args;
int sum = 0;
va_start(args,num);
int x = 0;
for(x = 0; x < num;x++)
sum += va_arg(args,int);
va_end(args);
return sum;
}
int main()
{
printf("Added 2 + 5 + 3: %d\n",add_all(3,2,5,3));
}
You use C varargs to write a variadic function. You'll need to include stdargs.h, which gives you macros for iterating over an argument list of unknown size: va_start, va_arg, and va_end, using a datatype: va_list.
Here's a mostly useless function that prints out it's variable length argument list:
void printArgs(const char *arg1, ...)
{
va_list args;
char *str;
if (arg1) We
va_start(args, arg1);
printf("%s ", arg1);
while ((str = va_arg(argp, char *)) != NULL)
printf("%s ", str);
va_end(args);
}
}
...
printArgs("print", "any", "number", "of", "arguments");
Here's a more interesting example that demonstrates that you can iterate over the argument list more than once.
Note that there are type safety issues using this feature; the wiki article addresses some of this.

Do C functions support an arbitrary number of arguments?

PHP has a func_get_args() for getting all function arguments, and JavaScript has the functions object.
I've written a very simple max() in C
int max(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
I'm pretty sure in most languages you can supply any number of arguments to their max() (or equivalent) built in. Can you do this in C?
I thought this question may have been what I wanted, but I don't think it is.
Please keep in mind I'm still learning too. :)
Many thanks.
You could write a variable-arguments function that takes the number of arguments, for example
#include <stdio.h>
#include <stdarg.h>
int sum(int numArgs, ...)
{
va_list args;
va_start(args, numArgs);
int ret = 0;
for(unsigned int i = 0; i < numArgs; ++i)
{
ret += va_arg(args, int);
}
va_end(args);
return ret;
}
int main()
{
printf("%d\n", sum(4, 1,3,3,7)); /* prints 14 */
}
The function assumes that each variable argument is an integer (see va_arg call).
Yes, C has the concept of variadic functions, which is similar to the way printf() allows a variable number of arguments.
A maximum function would look something like this:
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>
static int myMax (int quant, ...) {
va_list vlst;
int i;
int num;
int max = INT_MIN;
va_start (vlst, quant);
for (i = 0; i < quant; i++) {
if (i == 0) {
max = va_arg (vlst, int);
} else {
num = va_arg (vlst, int);
if (num > max) {
max = num;
}
}
}
va_end (vlst);
return max;
}
int main (void) {
printf ("Maximum is %d\n", myMax (5, 97, 5, 22, 5, 6));
printf ("Maximum is %d\n", myMax (0));
return 0;
}
This outputs:
Maximum is 97
Maximum is -2147483648
Note the use of the quant variable. There are generally two ways to indicate the end of your arguments, either a count up front (the 5) or a sentinel value at the back.
An example of the latter would be a list of pointers, passing NULL as the last. Since this max function needs to be able to handle the entire range of integers, a sentinel solution is not viable.
The printf function uses the former approach but slightly differently. It doesn't have a specific count, rather it uses the % fields in the format string to figure out the other arguments.
In fact, this are two questions. First of all C99 only requires that a C implementation may handle at least:
127 parameters in one function
definition
127 arguments in one function call
Now, to your real question, yes there are so-called variadic functions and macros in C99. The syntax for the declaration is with ... in the argument list. The implementation of variadic functions goes with macros from the stdarg.h header file.
here is a link to site that shows an example of using varargs in c Writing a ``varargs'' Function
You can use the va_args function to retrieve the optional arguments you pass to a function. And using this you can pass 0-n optional parameters. So you can support more then 2 arguments if you choose
Another alternative is to pass in an array, like main(). for example:
int myfunc(type* argarray, int argcount);
Yes, you can declare a variadic function in C. The most commonly used one is probably printf, which has a declaration that looks like the following
int printf(const char *format, ...);
The ... is how it declares that it accepts a variable number of arguments.
To access those argument it can uses va_start, va_arg and the like which are typically macros defined in stdarg.h. See here
It is probably also worth noting that you can often "confuse" such a function. For example the following call to printf will print whatever happens to be on the top of the stack when it is called. In reality this is probably the saved stack base pointer.
printf("%d");
C can have functions receive an arbitrary number of parameters.
You already know one: printf()
printf("Hello World\n");
printf("%s\n", "Hello World");
printf("%d + %d is %d\n", 2, 2, 2+2);
There is no max function which accepts an arbitrary number of parameters, but it's a good exercise for you to write your own.
Use <stdarg.h> and the va_list, va_start, va_arg, and va_end identifiers defined in that header.
http://www.kernel.org/doc/man-pages/online/pages/man3/stdarg.3.html

Resources