Saturday, September 21, 2013

How to work with Ellipsis Operator in C Language?

In my last post, I was talking about the printf function and there I said that printf uses ellipsis operator. In this post I would like to elaborate on how to use ellipsis in C program.

a. Here are some important points on Ellipsis
b. Ellipsis operator is expressed only with three dots (…) within the argument list of a function
c. Ellipsis must be the last argument in the argument list
d. The argument list containing the ellipsis must have at least another argument (other than the ellipsis) in the list. Let us call it as “Mandatory Argument”.

This Mandatory Argument must be placed just before the ellipsis and this Mandatory Argument must reflect the number of variable arguments currently being passed explicitly or implicitly.

Here I mean to say, Mandatory Argument can explicitly say that currently n numbers of variable arguments are being passed; in this case the prototype of the function would be something like

void foo(int no_of_variable_arguments, …)

Otherwise Mandatory argument may hide this information within any sort of other data types. For example if the numbers of variable arguments is an element of a structure of type Info, then a valid prototype would be

void foo(struct Info str, …)

If the numbers of variable arguments are passed implicitly then it becomes the responsibility of foo to determine (within the body code of foo) what the value of n from the given container is.

Let us take some more examples

void foo(int var1, int num, …) is a valid usage of ellipsis. Here num is working as Mandatory argument and the numbers of variable arguments actually being passed must be explicitly / implicitly determined through num. var1 is nothing but the optional argument , which might be there for any good reasons.

void foo( char* str, …) is again valid. Here the numbers of variable arguments being passed must be hidden within string str. parsing of str will give you the required value of n. The logic of parsing must be maintained within foo

Let us do a case study on our good old friend printf

The signature of printf is like
int printf(const char* formatString, …)

Here Mandatory Argument does the trick to hide the numbers and types of variable arguments currently being passed.  For example if I call printf like printf(“The results are %d, %d and %f”, I,j,k); then the string  “The results are %d, %d and %f” will implicitly say that there are three variable arguments that are being passed now and they are i, j and k. The proper parsing algorithm in printf will be able to count the numbers of format specifiers like %d or %f and this obviously hides the data types of variable arguments also.  Parsing of “The results are %d, %d and %f” essentially says that there would be three variable arguments and out of these three variable arguments, first two are ints and the third one is float .

Now let us go straight to “how to write the body of the function containing ellipsis as an argument”.

Ellipsis works with four different macros to deal with variable number of arguments; and they are va_list, va_start, va_arg and va_end. The va_list stores the variable arguments. The list is declared like
va_list anyList;

The va_start takes two arguments, the va_list itself and the Mandatory Argument. If the Mandatory Argument passed to the experimental function be integer x, then the call to va_start would be
va_start( anyList, x );
va_start initializes the va_list.

Next va_arg also takes two arguments, va_list itself with a particular data type. For example
va_arg(anyList,float);

Calling of this macro returns the next float from the anyList. 

Ultimately, va_end(anyList) will clean up anyList.

CODE EXAMPLE

The following code example shows how to write a function with variable number of arguments. The
code is self explanatory through commenting. Please give proper attention to the comment in red.

#include<stdio.h>
#include<stdlib.h>
#include <stdarg.h>
//defining the function with variable number of arguments
float findAverage(int numArg, ...)
{
      float avg;
      int sum = 0;
      int arg;
      int index;
      va_list list; //creating the variable list
      va_start(list,numArg); // initializing the list with numAg number of arguments
      for( index = 0 ; index < numArg; index++ )
      {
                  arg = va_arg( list, int );//retrieving the arguments. The prior knowledge of the argument is mandatory. Here in this case it is “int”
                  sum = sum + arg; 
      }
      avg = sum / numArg;
      va_end(list); //clearing up the list
      return avg;
}
int main(void)
{
      //calling the function with variable number of arguments
      printf("\n The average of 3, 4, 5 = %f\n", findAverage(3,3,4,5) );
      printf("\n The average of 6,7,8,9,10 = %f\n", findAverage(5,6, 7, 8, 9, 10));
      return 0;        
}

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.