?
Solved

How can I pass opetional arguments to C functions?

Posted on 2003-02-19
8
Medium Priority
?
339 Views
Last Modified: 2010-04-15

hi,

Is it possible to pass various amount of parameters to a C function (not to main(), but the other ones I define) to then read in that function and define what's optional and what's not?

Can read it with something like argc/argv like in main()?

I of cource tried, but without success and am not sure whether I do the things right. My guess is that this is not possible due the fact the pointers/types would get lost. Is that correct or am I missing it?

Thanks,
Maxim Maletsky
0
Comment
Question by:s-maxim
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
8 Comments
 
LVL 6

Expert Comment

by:gj62
ID: 7985215
Sure, look at printf, for example.

You use the ellipses - sample code below:

#include <stdio.h>
#include <stdarg.h> /* va_list, va_arg, va_end     */

int set(char *item, int num, ...);     /* Declare the function. Notice the ellipses ...        */

/************************************************************************/

main()
{
    char *item="pear";

    int   Ret;
     
    Ret = set (item,4, "apple", "pear", "banana", "grape");
     
    if (Ret)
    {
        printf ("%s found\n", item);
    }
    else
    {
        printf("%s not found\n", item);
    }
}

/************************************************************************/

int set(char *item, int num, ...)
{
    va_list ap;      /* define 'ap' It acts as a                     * pointer to the undefined
           * variables.               */
    int Ret=0;
    int Inc=0;   /* Assume the worst.            */
    va_start(ap, num);      /* seed 'ap'               */

    do
    {
        if ( item == va_arg(ap, char *))
        {
            Ret = 1;
        }
    } while ( Ret==0 && ++Inc < num);

    va_end(ap);          /* tidy up.               */
    return (Ret);
}


0
 
LVL 6

Accepted Solution

by:
gj62 earned 80 total points
ID: 7985225
Some more info:

A partial parameter list can be terminated by the ellipsis notation, a comma followed by three periods (, ...), to indicate that there may be more arguments passed to the function, but no more information is given about them. Type checking is not performed on such arguments. At least one parameter must precede the ellipsis notation and the ellipsis notation must be the last token in the parameter list. Without the ellipsis notation, the behavior of a function is undefined if it receives parameters in addition to those declared in the parameter list.

To call a function with a variable number of arguments, simply specify any number of arguments in the function call. An example is the printf function from the C run-time library. The function call must include one argument for each type name declared in the parameter list or the list of argument types.

Here's some more info from Microsoft:

The following example shows how the va_start, va_arg, and va_end macros, along with the va_list type (declared in STDARG.H), work together:

#include <stdio.h>
#include <stdarg.h>

//  Declaration, but not definition, of ShowVar.
int ShowVar( char *szTypes, ... );

void main()
{
    ShowVar( "fcsi", 32.4f, 'a', "Test string", 4 );
}
//  ShowVar takes a format string of the form
//   "ifcs", where each character specifies the
//   type of the argument in that position.
//
//  i = int
//  f = float
//  c = char
//  s = string (char *)
//
//  Following the format specification is a list
//   of n arguments, where n == strlen( szTypes ).
void ShowVar( char *szTypes, ... )
{
    va_list vl;
    int i;

    //  szTypes is the last argument specified; all
    //   others must be accessed using the variable-
    //   argument macros.
    va_start( vl, szTypes );

    // Step through the list.
    for( i = 0; szTypes[i] != '\0'; ++i )
    {
        union Printable_t
        {
            int     i;
            float   f;
            char    c;
            char   *s;
        } Printable;

        switch( szTypes[i] )    // Type to expect.
        {
        case 'i':
            Printable.i = va_arg( vl, int );
            printf( "%i\n", Printable.i );
            break;

        case 'f':
            Printable.f = va_arg( vl, float );
            printf( "%f\n", Printable.f );
            break;

        case 'c':
            Printable.c = va_arg( vl, char );
            printf( "%c\n", Printable.c );
            break;

        case 's':
            Printable.s = va_arg( vl, char * );
            printf( "%s\n", Printable.s );
            break;

        default:
            break;
        }
    }
    va_end( vl );
}

The preceding example illustrates these important concepts:

A list marker must be established as a variable of type va_list before any variable arguments are accessed. In the preceding example, the marker is called vl.


The individual arguments are accessed using the va_arg macro. The va_arg macro needs to be told the type of argument to retrieve so it can transfer the correct number of bytes from the stack. If an incorrect type of a size different than that supplied by the calling program is specified to va_arg, the results are unpredictable.


The result obtained using the va_arg macro should be explicitly cast to the desired type.


The va_end macro must be called to terminate variable-argument processing.


0
 
LVL 8

Expert Comment

by:ssnkumar
ID: 7985305
Do you want your function to work like main()!? Which can take 1 or 2 or 3 or no arguments? Or is it variable arguements as gj62 has explained?
I think the Q is not clear to me! Please clarify...

-Narendra
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 8

Expert Comment

by:akshayxx
ID: 7985322
>>>>Can read it with something like argc/argv like in main()?

argc and argv in the main is not example of variable number of arguments.
its only two arguments ..( in some obfuscated codes i have seen more)
 one is number of tokens and another is array of tokens .. token= character string tokens
every token from argv is just a string .. u cannot tell if its integer or double or what .. u have to pass another token for any such identification..

 if va_arg concept, as gj62 proposed above, sounds tough to you . ( though i would recommend va_arg concept).. u can also do something like what main does.. pass two variables one is lenght of tokens .. and another is array of tokens .. and then start parsing tokens..

there can be another solution also .. like this one
typedef enum VARTYPE{INT,CHAR,DOUBLE};//u can add more
typedef struct generic_type{
VARTYPE typ;
void * data;
}
 
then u can pass array of this struct ..to the function. and in function u can take ur variables out, one by one..

big headache in this would be filling up the arguments in the array , before passing to the function .. which inthe case of va_arg .. is done automatically.

.while in both cases u have to do some amount of effort while retrieving the values..

dont know why i m telling this alternative method.. .go ahead with stdarg   etc.
0
 
LVL 11

Expert Comment

by:cup
ID: 7985949
Note there are two variable arg include files: vararg.h and stdarg.h.  Do not mix them.  You may see vararg.h in older books - that is before ANSI C came out.  The ANSI std uses stdarg.h
0
 
LVL 2

Expert Comment

by:Kryp
ID: 7986905
>        if ( item == va_arg(ap, char *))
This is a very poor way of doing a string comparison.
It only 'works' because your implementation has removed duplicate string constants, so when you get to "pear"=="pear", you're comparing identical addresses.
0
 
LVL 1

Author Comment

by:s-maxim
ID: 7987804

I like what `gj62' writes about the strarg usage. I actually have it within my applciation from some third-party library, but again - wasn't sure how exactly to use it. Thanks for explaining it with a great example.

Maxim Maletsky
maxim@php.net
0
 
LVL 1

Author Comment

by:s-maxim
ID: 7987813

great and clear example. Thanks!
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.
Suggested Courses

771 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