Trouble Wrapping Printf in C Program - c

I'm trying to wrap printf in a C program (well, actually _snprintf but this example is simpler) and am having trouble getting the variable argument stuff to work. Here is my code:
#include <stdio.h>
#include <stdarg.h>
void works(void)
{
printf("%d\n", 100);
}
void wrap_printf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
printf(fmt, args);
va_end(args);
}
void broken(void)
{
wrap_printf("%d\n", 100);
}
int main(void)
{
works();
broken();
return 0;
}
Here is my output:
100
3668388
The args variable looks good after the call to va_start in my code, but as soon as I step into the C runtime code and they call va_start the value looks bad. Any thoughts as to what I might be doing wrong?

va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
You need to call vprintf instead of printf. The v*printf functions understand va_List arguments. I'm surprised you didn't get a warning.

You're passing args which is a va_list, but printf() of course expects the arguments directly, it has no way of knowing that its second argument suddenly is a va_list.
You should be using vprintf(), the variable-argument version which does indeed expect a va_list and knows how to extract the values from it.

Related

C vararg recursive function : what is the syntax?

I'm trying to make a recursive function with variable args in C, and I can't seem to pass the args when writing the recursive call.
Code:
void f(const char* s, ...) {
va_list args;
va_start(args, s);
f(s,args);
va_end(args);
}
}
Don't mind the infinite call stack. It's not the point here, so I discarded every other aspect in the code.
A va_list is an implementation-defined way to access arguments of a function you don't know at compile time -- for example (depending on the architecture) a pointer somewhere in the stack frame of the function. You can't use it in place of actual arguments.
If you need to pass on variadic arguments, the typical approach is to have your implementation in a function that takes a va_list argument. The idiomatic way to name that function is to prepend a v to its name. So in the end, you have two functions:
void vf(const char* s, va_list ap) {
// your logic ...
vf(s, ap); // recursive call
}
// just a wrapper:
void f(const char* s, ...) {
va_list args;
va_start(args, s);
vf(s, args);
va_end(args);
}
Note that this passes on a reference to the arguments your function was originally called with. If this is a problem for your logic, you can copy the whole argument list with the va_copy macro.

First argument is wrong when passing __VA_ARGS__

I'm trying to pass __ VA_ARGS __ to a function. For some reason the first argument is always wrong (seems like an address):
#define PRINTF_ERROR(format, ...) {\
PrintfError(format, __FUNCTION__, ##__VA_ARGS__);\
}
void PrintfError(const char* format, const char* function, ...)
{
va_list args;
va_start(args, format);
printf("%s(): ", function);
printf(format, args);
va_end(args);
}
For example, when trying to print the same variable:
"A = 0x20005524 A = 0x00000007"
Does anybody know why?
Thanks
There are two problem here.
First, va_start expects the last named parameter of the current function as its second parameter. In this case that would be function.
The second issue is that you're passing a va_list into printf. You should be calling vprintf instead.
void PrintfError(const char* format, const char* function, ...)
{
va_list args;
va_start(args, function); // pass "function" instead of "format"
printf("%s(): ", function);
vprintf(format, args); // call vprintf
va_end(args);
}
You've got the order of your parameters wrong. The one you pass to va_start() has to be the one before the ... because it's used to work out where the extra arguments start
So your function should look like this...
void PrintfError(const char* function, const char* format, ...)
{
va_list args;
va_start(args, format);
From man va_start:
void va_start(va_list ap, last);
[...]
DESCRIPTION
va_start()
[...]
The argument last is the name of the last argument before the variable argument list, that is, the last argument of which the calling function knows the type.
So given
void PrintfError(const char* format, const char* function, ...)
just change
va_start(args, format);
to be
va_start(args, function);
Also this
printf(format, args);
(which probably is a typo) should be
vprintf(format, args);
Unrelated to your question, here
#define PRINTF_ERROR(format, ...) {\
PrintfError(format, __FUNCTION__, ##__VA_ARGS__);\
}
the curly braces are only half the way to make this safe.
Better do
#define PRINTF_ERROR(format, ...) do {\
PrintfError(format, __FUNCTION__, __VA_ARGS__);\
} while (0)
Also no need for the ##.

Forward Variadic Argument List to ncurses printw function in c

This has been asked in several different flavors. Yet I can still not get it to work. Here is my function definition.
void
ncurses_add_line(const char *fmt, ...)
{
if (ncurses_window) {
va_list args;
va_start(args, fmt);
printw(fmt, args);
printw("\n");
va_end(args);
}
}
When I call this function I get gibberish in the variadic print out of my function. If I call printw directly it all works. For example, if I call ncurses_add_line like ncurses_add_line("Hello %d", var) I get a value not store in var. However, if I call printw("Hello %d", var), I see the value of var displayed next to "Hello" as in, if var == 1 then "Hello 1" is printed with printw but this is not the case for ncurses_add_line.
What do I need to change?
My reason for wrapping this up is because I don't want to include in my header file, only in my c file.
Try vwprintw instead of printw. vwprintw takes a va_list as its argument.
The idiom you're trying to use -- passing a va_list to a function that takes a variable number of arguments -- won't work. One solution is to find a variant of the function that will work (in this case, vwprintw). An alternative is to "flatten" the va_list: in this case, you could use vsprintf to create a formatted string, and then pass that into curses.
args is not something like an array of arguments. It is an internal structure. You have to read out every single argument by passing the type. Please keep in mind, that in C there is no runtime reflection, so you have to add the types in your code.
void ncurses_add_line(const char *fmt, ...)
{
if (ncurses_window)
{
va_list args;
va_start(args, fmt);
char *arg = va_arg( args, int ); // take out one arg by giving the type (int)
printw(fmt, arg);
printw("\n");
va_end(args);
}
}

converting va_list to variable argument? [duplicate]

This question already has answers here:
Passing variable arguments to another function that accepts a variable argument list
(11 answers)
Closed 8 years ago.
I have a function log_message it takes variable arguments.
log_message(int level, char *fmt, ...)
now before calling this(log_message) function i have to add new function(_log_message), and new function will call log_message.
_log_message(int level, char *fmt, ...)
new function is also same. when _log_message will call log_message it will convert variable input to va_list. Now i have va_list, i don't wanna change the original one, is there any way to change back to variable input, so i will able to call the original one(log_message).
No, there is no way to turn a va_list back into a list of arguments.
The usual approach is to define a base function which takes a va_list as an argument. For example, the standard C library defines printf and vprintf; the first is a varargs function and the second has exactly the same functionality but takes a va_list instead. Similarly, it defines fprintf and vfprintf. It's trivial to define printf, vprintf and fprintf in terms of vfprintf:
int fprintf(FILE* stream, const char* format, ...) {
va_list ap;
va_start(ap, format);
int n = vfprintf(stream, format, ap);
va_end(ap);
return n;
}
int vprintf(const char* format, va_list ap) {
return vfprintf(stdout, format, ap);
}
int printf(const char* format, ...) {
va_list ap;
va_start(ap, format);
int n = vprintf(format, ap);
va_end(ap);
return n;
}
(Similarly for the various exec* functions, which come in both va_list and varargs varieties.)
I'd suggest you adopt a similar strategy.

Function arguments like printf in C

I want to implement a function Myprintf() that takes arguments like printf().
Now I am doing this by:
sprintf(demoString, "Num=%d String=%s", num, str);
Myprintf(demoString);
I want to replace this function call as:
Myprintf("Num=%d String=%s", num, str);
How is this possible?
#include <stdio.h>
#include <stdarg.h>
extern int Myprintf(const char *fmt, ...);
int Myprintf(const char *fmt, ...)
{
char buffer[4096];
va_list args;
va_start(args, fmt);
int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
va_end(args);
...print the formatted buffer...
return rc;
}
It isn't clear from your question exactly how the output is done; your existing Myprintf() presumably outputs it somewhere, maybe with fprintf(). If that's the case, you might write instead:
int Myprintf(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
int rc = vfprintf(debug_fp, fmt, args);
va_end(args);
return rc;
}
If you don't want to use the return value, declare the function as void and don't bother with the variable rc.
This is a fairly common pattern for 'printf() cover functions'.
You need to define a function with variable arguments, and use vsprintf to build the string.
The printf and its relatives are in a family of functions called variadic functions and there are macros/functions in the <stddef.h> header in the C standard library to manipulate variadic argument lists. Look at the GNU docs for examples: How Variadic Functions are Defined and Used.

Resources