I have been trying to pass variable arguments to other function in C but it is producing inconsistent result in different runtime environment as well as in different runs in same environment:
int main()
{
int result = myprintf("Something \n %d", 9);
return result;
}
int myprintf(const char *format, ...){
printf("Something \n %d", 9);
printf("\n");
va_list args;
va_start(args, format);
int result = printf(format,args);
printf("\n");
va_end(args);
return result;
}
And the result produced is:
WWW.FIRMCODES.COM
9
WWW.FIRMCODES.COM
438656664
I could not find the reason for "438656664".
You cannot pass the variadic arguments to a variadic function. Instead, you must call a function that takes a va_list as argument. The standard library provides variants of printf and scanf that take a va_list; their names have the prefix v.
Your example should look like:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
int printfln(const char *format, ...)
{
int result;
va_list args;
va_start(args, format);
result = vprintf(format, args);
printf("\n");
va_end(args);
return result;
}
int main()
{
int result = printfln("Something \n %d", 9);
printf("(%d)\n", result);
return 0;
}
There are some gotchas, for example when you want to call two v... function for printing to the screen and a log file: The v... function may exhaust the va_list, so you must pass in a fresh one to each call if your code should be portable.
For the C++ fellow also reading this. You can actually do it using pack expansion without using vprintf.
This trick is quite handy when you need to wrap a method that takes the ellipsis (...)
and not a va_list.
For instance:
template <class ... Args>
void foo(const char *format, Args ... args)
{
printf(format, args...);
}
Here class ... Args is template parameter pack, Args ... args is function parameter pack, and args... is function parameter pack expansion.
Alternatively, you can simply use a wrapper macro:
#include <stdio.h>
#define myprintf(fmt, ...) ( printf("Something \n %d\n", 9), printf(fmt, __VA_ARGS__) )
int main (void)
{
int result = myprintf("Something \n %d\n", 9);
printf("%d\n", result);
}
Note the use of the comma operator to preserve the returned value of the right-hand printf call to the caller.
This isn't any less type safe than the (equally dangerous) stdarg.h variadic functions.
Just a simple demonstration and worked example with "a fresh one va_list" when you need to print/output-as-string a template string like constexpr const char* example = R"(template "%s")"; .
std::string print_templ(const char* format, ...)
{
va_list args1;
va_start(args1, format);
va_list args2;
va_copy(args2, args1);
std::vector<char> str(std::vsnprintf(nullptr, 0, format, args1) + 1);
va_end(args1);
const int ret = std::vsnprintf(str.data(), str.size(), format, args2);
va_end(args2);
return std::string(str.begin(), str.begin()+ret);
}
Related
I want to only printf if some condition is true. I know printf is a variadic function but sadly I can't seem to find any thread here explaining I can wrap it.
Basically every in the code where I'd write :
printf(" [text and format] ", ... args ...);
I want to write something like
my_custom_printf(" [text and format] ", ... args ...);
Which then is implemented like this :
int my_custom_printf(const char* text_and_format, ... args ...)
{
if(some_condition)
{
printf(text_and_format, ... args...);
}
}
A first version of the condition would be independent of the args (it would be on some global variable), but it might be in the future that it's a condition on argument that's wanted.
Anyway, right now I just need the syntax for ... args ... in the prototype and the body of my_custom_printf.
I'm using GCC but I don't know which C standard - but we can just try stuff out.
You can use vprintf:
#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>
static bool canPrint = true;
int myprintf(const char *fmt, ...)
{
va_list ap;
int res = 0;
if (canPrint) {
va_start(ap, fmt);
res = vprintf(fmt, ap);
va_end(ap);
}
return res;
}
int main(void)
{
myprintf("%d %s\n", 1, "Hello");
return 0;
}
void TestPrint(char* format, ...)
{
va_list argList;
va_start(argList, format);
printf(format, argList);
va_end(argList);
}
int main()
{
TestPrint("Test print %s %d\n", "string", 55);
return 0;
}
I need to get:
Test print string 55
Actually, I get garbage output. What is wrong in this code?
Use vprintf() instead.
Instead of printf, I recommend you try vprintf instead, which was created for this specific purpose:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void errmsg( const char* format, ... )
{
va_list arglist;
printf( "Error: " );
va_start( arglist, format );
vprintf( format, arglist );
va_end( arglist );
}
int main( void )
{
errmsg( "%s %d %s", "Failed", 100, "times" );
return EXIT_SUCCESS;
}
Source
As others have pointed out already: In this case you should use vprintf instead.
But if you really want to wrap printf, or want to wrap a function that does not have a v... version, you can do that in GCC using the non-standard __builtin_apply feature:
int myfunction(char *fmt, ...)
{
void *arg = __builtin_apply_args();
void *ret = __builtin_apply((void*)printf, arg, 100);
__builtin_return(ret);
}
The last argument to __builtin_apply is the max. total size of the arguments in bytes. Make sure that you use a value here that is large enough.
This is not how you use printf(). If you want to use va_lists, use vprintf() instead. Look here for reference.
I am making a C library that creates a print function, which basically executes printf. Because of this, I wish to create a duplicate of printf from glibc, but with the name print. How can I duplicate this function without duplicating all of it's code?
(I found the code here but don't understand how to duplicate it in my library, or if it is legal to do so.)
There you go:
#include <stdarg.h>
void println(const char* format,...)
{
va_list args;
va_start(args,format);
vprintf(format,args);
printf("\n");
va_end(args);
}
You can use a variadic macro:
#define println(...) (printf(__VA_ARGS__), (void) puts(""))
You can either use a Macro:
#define print printf
or define a wrapper function
int print( char *fmt, ... )
{
va_list ap;
int n;
va_start(ap, fmt);
n = vprintf(fmt, ap);
va_end(ap);
return n;
}
So, here's a small problem I'm facing right now -> I'm trying to write a function that will accept a char* message and a variable number of arguments. My function will modify the message a little, and then It'll call printf with the message and given parameters. Essentialy, I'm trying to write something like that:
void modifyAndPrintMessage(char* message,...){
char* newMessage; //copy message.
//Here I'm modifying the newMessage to be printed,and then I'd like to print it.
//passed args won't be changed in any way.
printf(newMessage,...); //Of course, this won't work. Any ideas?
fflush(stdout);
}
So, anybody knows what should I do to make it happen? I'd be most grateful for any help :)
You want to use varargs...
void modifyAndPrintMessage( char* message, ... )
{
// do somehthing custom
va_list args;
va_start( args, message );
vprintf( newMessage, args );
va_end( args );
}
void modifyAndPrintMessage(char* message,...)
{ char newMessage[1024]; // **Make sure the buffer is large enough**
va_list args;
va_start(args, message);
vsnprintf(newMessage, message, args);
printf(newMessage);
fflush(stdout);
}
Use varargs to accept variable number of parameters then use sprintf to create the new message
You can use va_list from stdarg.h,
C example: http://www.tutorialspoint.com/cprogramming/c_variable_arguments.htm
C++ example: http://www.cprogramming.com/tutorial/lesson17.html.
An of course, see the man page: http://linux.die.net/man/3/stdarg
Man page example for reference:
#include <stdio.h>
#include <stdarg.h>
void
foo(char *fmt, ...)
{
va_list ap;
int d;
char c, *s;
va_start(ap, fmt);
while (*fmt)
switch (*fmt++) {
case 's': /* string */
s = va_arg(ap, char *);
printf("string %s\n", s);
break;
case 'd': /* int */
d = va_arg(ap, int);
printf("int %d\n", d);
break;
case 'c': /* char */
/* need a cast here since va_arg only
takes fully promoted types */
c = (char) va_arg(ap, int);
printf("char %c\n", c);
break;
}
va_end(ap);
}
There is a library which includes this functionality. Here is some example code from the reference:
#include <stdarg.h> /* va_list, va_start, va_arg, va_end */
int FindMax (int n, ...)
{
int i,val,largest;
va_list vl;
va_start(vl,n);
largest=va_arg(vl,int);
for (i=1;i<n;i++)
{
val=va_arg(vl,int);
largest=(largest>val)?largest:val;
}
va_end(vl);
return largest;
}
The ellipsis is actually valid code, and you can use the va_list object to parse a variable number of parameters.
void TestPrint(char* format, ...)
{
va_list argList;
va_start(argList, format);
printf(format, argList);
va_end(argList);
}
int main()
{
TestPrint("Test print %s %d\n", "string", 55);
return 0;
}
I need to get:
Test print string 55
Actually, I get garbage output. What is wrong in this code?
Use vprintf() instead.
Instead of printf, I recommend you try vprintf instead, which was created for this specific purpose:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void errmsg( const char* format, ... )
{
va_list arglist;
printf( "Error: " );
va_start( arglist, format );
vprintf( format, arglist );
va_end( arglist );
}
int main( void )
{
errmsg( "%s %d %s", "Failed", 100, "times" );
return EXIT_SUCCESS;
}
Source
As others have pointed out already: In this case you should use vprintf instead.
But if you really want to wrap printf, or want to wrap a function that does not have a v... version, you can do that in GCC using the non-standard __builtin_apply feature:
int myfunction(char *fmt, ...)
{
void *arg = __builtin_apply_args();
void *ret = __builtin_apply((void*)printf, arg, 100);
__builtin_return(ret);
}
The last argument to __builtin_apply is the max. total size of the arguments in bytes. Make sure that you use a value here that is large enough.
This is not how you use printf(). If you want to use va_lists, use vprintf() instead. Look here for reference.