The details of how arguments are passed to a function is the "calling convention." Depending on platform, language, and compiler, the rules can be complex. So it is not safe to assume the x_1 is on the stack and *(ptr + 1) is the first argument after x_1. The purpose of stdarg.h is to provide a portable way to iterate through the variable arguments.
To use stdarg.h, a function needs three things:
- At least one fixed argument
- A way to determine the number of variable arguments
- A way to determine the type of each variable arugment
Functions like printf have a format string that is both a fixed argument and it encodes the number and type of each variable argument.
For value, the the first argument n is a fixed argument and it gives the number of variable arguments. There isn't a clear way to determine the type of each variable argument for value. One option is to make a choice, for example "int", and document the function. Since the operation inside the for-loop is division, maybe float or double makes more sense.
Using stdarg.h is straight-forward in this case. Use va_start to initialize a va_list and then use va_arg to get the value of each variable argument.
/* value inputs n variable arguments, call them x_i, of type int
* and returns the value
*
* (x_0 / x_1) + (x_2 / x_3) + ...
*
* n must be even
* the division is integer division
*/
int value(int n, ...)
{
int result = 0;
va_list ap;
va_start(ap, n);
for (int i = 0; i < n/2; ++i) {
int a = va_arg(ap, int);
int b = va_arg(ap, int);
result += a/b;
}
va_end(ap);
return result;
}
Example Calls
This example computes (6/3) + (21/7):
int r = value(4, 6, 3, 21, 7);
printf("%d\n", r);
and results in
5
This second example shows that value can be called by unpacking an array
int a[] = {49, 7, 64, 8, 121, 11};
int r = value(6, a[0], a[1], a[2], a[3], a[4], a[5]);
printf("%d\n", r);
which results in
26