passing variable number of arguments - c

Can we pass variable number of arguments to a function in c?

Here is an example:
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
int maxof(int, ...) ;
void f(void);
int main(void){
f();
exit(EXIT SUCCESS);
}
int maxof(int n_args, ...){
register int i;
int max, a;
va_list ap;
va_start(ap, n_args);
max = va_arg(ap, int);
for(i = 2; i <= n_args; i++) {
if((a = va_arg(ap, int)) > max)
max = a;
}
va_end(ap);
return max;
}
void f(void) {
int i = 5;
int j[256];
j[42] = 24;
printf("%d\n", maxof(3, i, j[42], 0));
}

If it is a function that accepts a variable number of arguments, yes.

Yes, if the function accepts variable arguments. If you need to make your own variable-argument function, there are macros that begin with va_ which give you access to the arguments.

make sure that the variable argument list should always be at the end of the argument list
example: void func(float a, int b, ...) is correct
but void func(float a, ..., int b) is not valid

"You should consider that using variadic functions (C-style) is a dangerous flaw," says Stephane Rolland. You can find his helpful post here.

Related

Getting the size of varargs in C?

I am trying to convert some Java code into C. The Java code goes like this:
public static int minimum( int... minimum ) {
assert( minimum.length > 0 );
if ( minimum.length > 0 )
.... // some code that i am able to translate to C without any hassle
}
Now I understand how to have varargs in C by using the stdarg.h header and using the macros provided. However I am stuck doing the minimum.length part.
I have tried strlen but the terminal is giving me an incompatible integer to pointer conversion warning. Is there any way in C where I can replicate the same thing that Java does?
Not directly, as pointed out by #MichaelBurr, you need to pass the number of elements or use a sentinel.
An indirect way to do this is using compound literals:
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>
#define minimum(...) fnminimum(sizeof((int []) {__VA_ARGS__}) / sizeof(int), __VA_ARGS__)
static int fnminimum(int n, ...)
{
int num, min = INT_MAX;
va_list ap;
va_start(ap, n);
while (n--) {
num = va_arg(ap, int);
if (num < min) {
min = num;
}
}
va_end(ap);
return min;
}
int main(void)
{
int a = 1;
printf("%d\n", minimum(2, 30, 7, a++, 4));
return 0;
}
Another (ugly) method using NARGS macros (limited to N args):
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define minimum(...) fnminimum(NARGS(__VA_ARGS__), __VA_ARGS__)
static int fnminimum(int n, ...)
{
int num, min = INT_MAX;
va_list ap;
va_start(ap, n);
while (n--) {
num = va_arg(ap, int);
if (num < min) {
min = num;
}
}
va_end(ap);
return min;
}
int main(void)
{
printf("%d\n", minimum(2, 30, 7, 1, 4));
return 0;
}
Output:
1
There is no built-in way to get the number of vararg arguments passed in C.
You need to do one of the following:
pass in a count explicitly,
pass in a count implicitly (as printf() does via the number of conversion specifiers)
or use a sentinel value (such as NULL or 0) to indicate the end of the vararg list
I have seen schemes that use macros and the __VA_ARGS__ identifier to automatically place a sentinel at the end of the varargs list when calling a function.

pointer to function c language basic

This is my first time working with pointers to function.
What I'm trying to do is create a function called essay, that gets a pointer to another function , an integer num, and then num doubles.
The function essay, will multiply the arguments, and then return the value of the function i recieved as an argument, with the product.
This sounds complex but it really is quite simple.
Example:
essay(sin,2,pi,1/2) will return the value of sin(pi/2)
this is my code...for some reason it doesnt let me send the pointer to the function sin. Says no instance of overloaded function sin matches argument list, but this is exactly how i saw my teacher do it...I think.
#include <stdio.h>
#include <conio.h>
#include <stdarg.h>
#include <math.h>
double (*pfunc)(double);
double essay(double* pfunc(double),double num, ... )
{
int i;
double product=1,result;
va_list arguments;
va_start(arguments,num);
for(i=0;i<num;i++)
product*=va_arg(arguments,double);
va_end(arguments);
result=*(pfunc(product));
return result;
}
void main()
{
double x,y;
x=3.14159265358979323846;
y=0.5;
printf("%lf",essay(sin,2,x,y));
getch();
}
this is wrong
double essay(double* pfunc(double),double num, ... )
Here you're passing a function as a parameter which return a pointer to double, that not make sense, should be:
double essay(double (*pfunc)(double),double num, ... )
Here you're passing a pointer to a function which returns a double and receive a double as a parameter
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
// removed extra var
double essay(double (*pfunc)(double), double num, ...) // added parens
{
int i;
double product = 1, result;
va_list arguments;
va_start(arguments, num);
for (i = 0; i < num; i++)
product *= va_arg(arguments, double);
va_end(arguments);
result = pfunc(product); // removed extra parens
return result;
}
void main()
{
double x, y;
x = 3.14159265358979323846;
y = 0.5;
printf("%lf", essay(sin, 2, x, y));
}
This is what I'd do, assuming a C99 compiler that accepts variable declarations in for loops and at arbitrary points in a block of code. Note the use of the typedef for the function pointer type (MathFunc2 would be for a function that takes two arguments, etc), and the use of int (rather than double) for the number of values in the argument list.
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
typedef double (*MathFunc1)(double);
static double essay(MathFunc1 function, int num, ...)
{
double product = 1.0;
va_list arguments;
va_start(arguments, num);
for (int i = 0; i < num; i++)
product *= va_arg(arguments, double);
va_end(arguments);
double result = (*function)(product);
return result;
}
int main(void)
{
double x = 3.14159265358979323846; // M_PI?
double y = 0.5;
printf("%f\n", essay(sin, 2, x, y));
}

Get variable arguments directly from stack

I'm playing with the stack and function's call parameters.
What I want to achieve here is to get the value of variable parameters directly using the stack.
It works (or seems to work) fine when I don't use variable parameters.
Here is what is working:
void test(int a, int b)
{
unsigned char *ptr;
int i;
ptr = (unsigned char*)&a;
for (i = 0; i < 4; i++)
{
printf("%d,", *ptr);
}
}
That works, I can retrieve the value of b;
The same code using
void test(int a, ...);
as function's prototype doesn't work.
I cant understand what's going on here.
Can you help me?
Thanks !
Edit:
Ok, then it seeems there is no stable and reliable way to do that kind of stuff on my own.
Lets say that in the callee function I know the data size (but not the type) of variable argument, is there a way to grab them ?
As long as you know or can determine the number of arguments, you can use the macros from <stdarg.h>:
#include <stdio.h>
#include <stdarg.h>
void test1(int n, ...)
{
va_list args;
va_start(args, n);
for (int i = 0; i < n; i++)
{
int j = va_arg(args, int);
printf("%d: %d\n", i, j);
}
va_end(args);
}
void test2(int a, ...)
{
va_list args;
int i = 0;
printf("%d: %d\n", i++, a);
va_start(args, a);
int j;
while ((j = va_arg(args, int)) > 0)
printf("%d: %d\n", i++, j);
va_end(args);
}
The difference is in how these two functions are called:
int main(void)
{
test1(4, 1, 3, 7, 9);
test2(1, 3, 7, 9, 0);
return(0);
}
The printf() family uses an alternative but equivalent technique; those functions scan the format string and determine the type of each argument (as well as the number of arguments) from the information in the format string. So, your main options are:
count - test1()
sentinel - test2()
format string - printf()
In functions with ... you can use va_* macro
void test(int a, ...) {
va_list ap;
va_start(ap, a);
// Your code
va_end(ap);
}

What does "implicit declaration of function" mean?

#include <stdio.h>
int main()
{
int a = 4;
int b = 3;
addNumbers(a, b);
}
int addNumbers(int a, int b)
{
return a + b;
}
Why does this not compile, I get a message saying implicit declaration of function addNumbers()?
Either define the function before main() or provide its prototype before main().
So either do this:
#include <stdio.h>
int addNumbers(int a, int b)
{ //definition
}
int main()
{ //Code in main
addNumbers(a, b);
}
or this:
#include <stdio.h>
int addNumbers(int, int);
int main()
{ //Code in main
addNumbers(a, b);
}
int addNumbers(int a, int b)
{ // definition
}
You need to declare the function before you call it in main(). Either move it before main or at least declare it there.
Also, you should prob add return 0 at the end of the main function since it's supposed to return int.
#include <stdio.h>
int addNumbers(int a, int b)
{
return a + b;
}
int main()
{
int a = 4;
int b = 3;
addNumbers(a, b);
return 0;
}
You have to either move the entire addNumber() function above main or provide a prototype. The latter is done the following way:
int addNumbers(int a, int b);
int main()
{
// code of main() here
}
int addNumbers(int a, int b)
{
//code of addNumbers() here
}
Put addNumbers before main
int addNumbers(int a, int b)
{
return a + b;
}
int main()
{
int a = 4;
int b = 3;
addNumbers(a, b);
}
UPDATE:
To print it, printf("%i",addNumbers(a, b)); will display 7 in above case.
You can move the whole function above the point where it is called, or use a function prototype, like this:
#include <stdio.h>
int addNumbers(int a, int b); // function prototype
int main()
{
int a = 4;
int b = 3;
addNumbers(a, b);
}
int addNumbers(int a, int b)
{
return a + b;
}
You'll need a forward declaration of the addNumbers function or its definition moved up before the first usage:
// 2161304
#include <stdio.h>
// forward declaration
int addNumbers(int a, int b);
int main()
{
int a = 4;
int b = 3;
addNumbers(a, b);
}
// alternatively move this up before main ...
int addNumbers(int a, int b)
{
return a + b;
}
Regarding main and return:
Programs will compile without. The signatures of main defined by the standard are:
int main(void)
int main(int argc, char **argv)
There are three portable return values:
0, EXIT_SUCCESS, EXIT_FAILURE
which are defined in stdlib.h.
Declare the function before using it by either adding a prototype before main():
int addNumbers(int a, int b);
or move the whole addNumbers function before main().
I agree with declaration and definition thing but i am not getting any compilation errors with the above code.My gcc version is "4.4.1-4ubuntu9".Any ideas.
I have done a little modification to test the code.
#include <stdio.h>
int main()
{
int a = 4;
int b = 3;
printf("%d", addNumbers(a, b)); // Printf added.
}
int addNumbers(int a, int b)
{
return a + b;
}
You must declare the function before using.
Remember these 4 basic parts while dealing with functions.
Declaration
Call
Definition
Return
if your compiler is C99 standard it throws and error "implicit declaration", since since default promotion is obsolete in C99 standard.
if you try to compile with C89 standard this would be allowable.
In C99 standard function prototype is necessary
Since the compiler executes one line after another,by the time it sees the function call,it has to have the information about that function which the main function is calling.so my friend u need to tell the compiler about the function before you can ever use it.

How can I pass any number of arguments in User define function in C?

How can I pass any number of arguments in User define function in C?what is the prototype of that function?It is similar to printf which can accept any number of arguments.
Look here for an example.
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
int maxof(int, ...) ;
void f(void);
main(){
f();
exit(EXIT SUCCESS);
}
int maxof(int n args, ...){
register int i;
int max, a;
va_list ap;
va_start(ap, n args);
max = va_arg(ap, int);
for(i = 2; i <= n_args; i++) {
if((a = va_arg(ap, int)) > max)
max = a;
}
va_end(ap);
return max;
}
void f(void) {
int i = 5;
int j[256];
j[42] = 24;
printf("%d\n",maxof(3, i, j[42], 0));
}
Such a function is calle variadic, but such functions are much less useful than they might at first seem. The wikipedia page on the topic is not bad, and has C code.
The basic problem with such functions is that the number of parameters cannot in fact be variable - they are must be fixed at compile time by a known parameter. This is obvious in printf:
printf( "%s %d", "Value is", 42 );
The number of % specifiers must match the number of actual values, and this is true for all other uses of variadic functions in C, in one form or another.

Resources