Solved

How do I specify a variable number of parameters to a funciton?

Posted on 1998-06-06
5
273 Views
Last Modified: 2010-04-15
For example, I have the following function:

void openFiles(const char *fileName,...)

This function may have passed any number of parameters, so I cannot simply name them 'fileName1, fileName2, etc.'  I already know that  the (fileName, ...) is acceptable for a prototype.  However, I don't know how to access any arguments that are passed in beyond fileName.



 
0
Comment
Question by:Marc_P
5 Comments
 
LVL 2

Accepted Solution

by:
Slarti earned 70 total points
ID: 1251137
The idea is to use the address of the parameters. They are passed through the stack, and appear in sequential order.
Please see details in the comment below.
0
 
LVL 2

Expert Comment

by:Slarti
ID: 1251138
Passing parameters to functions is performed through the stack. This is all handled through the compiler, so you don't really have to know anything about it, but you need to know how it works to fiddle around with things like variable parameter lists.

Parameters are passed to the stack in the following order in the C calling convention (as opposed to Pascal, which is the other way around): The last parameter is pushed first, then the next-to-last, and so on. So, the way to access the next parameter after fileName is to take fileName's address and then move to the previous address. Now, this means that you will have to know the exact size of the other arguments, as well as their data type. (This is why functions like printf have a string which specifies the type and number of parameters.)

For example, let's say that you want to access the parameter immediately after fileName, and that that parameter is an int. Here is what you do:

// ... fileName is a parameter
int * pNextParam = (int*)(void*)&fileName;
pNextParam--; // move pointer back, to previous parameter
int nNextParam = * pNextParam;
// next parameter stored in nNextParam

Please note that on some systems, the stack grows downwards (i.e. previous elements are found in higher memory areas, not lower memory areas as depicted in the above code segment, so that the -- above may need to be changed to ++. This is architecture-dependent, that is, generally all x86 systems will have one convention, all Macs will have a different convention and so on. I believe the above code will work for x86 systems - perhaps someone can verify this?

If you want more information about the C calling convension, visit http://www.mcs.vuw.ac.nz/comp/Courses/203/1997/Labs/Lab2/

Good luck!
-- Slarti
0
 
LVL 84

Expert Comment

by:ozo
ID: 1251139
Or if you want to be portable, use the ANSI header <stdarg.h>
and the macros va_start(va_list ap, fileName), va_arg(va_list ap, type), va_end(ap)


0
 
LVL 11

Expert Comment

by:alexo
ID: 1251140
Please not e that Slarti's solution will not work with arguments of different sizes (not to mention being extremely unportable, thus having good chances of not working at all on your compiler of choice).  Ozo's comment provides a *standard* way of doing it.

Here's an example:

    #include <stdio.h>
    #include <stdarg.h>
    int average( int first, ... );

    void main( void )
    {
       /* Call with 3 integers (-1 is used as terminator). */
       printf( "Average is: 5Cn", average( 2, 3, 4, -1 ) );

       /* Call with 4 integers. */
       printf( "Average is: 5Cn", average( 5, 7, 9, 11, -1 ) );

       /* Call with just -1 terminator. */
       printf( "Average is: 5Cn", average( -1 ) );
    }

    /* Returns the average of a variable list of integers. */
    int average( int first, ... )
    {
       int count = 0, sum = 0, i = first;
       va_list marker;

       va_start( marker, first );     /* Initialize variable arguments. */
       while( i != -1 )
       {
          sum += i;
          count++;
          i = va_arg( marker, int);
       }
       va_end( marker );              /* Reset variable arguments.      */
       return( sum ? (sum / count) : 0 );
    }

Output
-----------  
Average is: 3
Average is: 8
Average is: 0

0
 

Expert Comment

by:amrish060998
ID: 1251141
Just need to know more about va_list, va_start, va_arg a,d va_end.


0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now