Counting parameters 
Author Message
 Counting parameters

How can I count the number of parameters passed to a function that
accepts a variable number of parameters (C calling convention)?

Parameters are pushed on the stack from right to left... correct?

Isn't there some kind of calculation between the current stack pointer
and the saved base pointer than I can use to figure out how many
parameters were passed?

--Dave

--



Wed, 19 Jun 2002 03:00:00 GMT  
 Counting parameters
Dave Navarro a crit dans le message ...

Quote:
>How can I count the number of parameters passed to a function that
>accepts a variable number of parameters (C calling convention)?

>Parameters are pushed on the stack from right to left... correct?

Sometimes. There is no 'stack' in C. This is compiler dependent.

Quote:
>Isn't there some kind of calculation between the current stack pointer
>and the saved base pointer than I can use to figure out how many
>parameters were passed?

All you need is to use the <stdarg.h> header and the  provided.functions (or
macros) See your C manual about va_*.

Note : You have x-posted to 5 newsgroup without positioning a follow-up to,
that is a VBT (Very Bad Thing).

--
-hs-
CLC-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
ISO-C Library: http://www.dinkum.com/htm_cl
"It's specified. But anyone who writes code like that should be
transmogrified into earthworms and fed to ducks." -- Chris Dollin CLC

--



Fri, 21 Jun 2002 03:00:00 GMT  
 Counting parameters
Hi Dave,

this would be one way to do it, but I cannot think of a *portable* way to
access the stack
pointer :-)

--
Kindest Regards,
Guus Leeuw


Quote:
> How can I count the number of parameters passed to a function that
> accepts a variable number of parameters (C calling convention)?

> Parameters are pushed on the stack from right to left... correct?

> Isn't there some kind of calculation between the current stack pointer
> and the saved base pointer than I can use to figure out how many
> parameters were passed?

> --Dave

> --


--



Fri, 21 Jun 2002 03:00:00 GMT  
 Counting parameters

Quote:

>How can I count the number of parameters passed to a function that
>accepts a variable number of parameters (C calling convention)?

>Parameters are pushed on the stack from right to left... correct?

     What stack?  There isn't necessarily one.

Quote:
>Isn't there some kind of calculation between the current stack pointer
>and the saved base pointer than I can use to figure out how many
>parameters were passed?

     Not that wouldn't be specific to an implementation.

Sincerely,

Gene Wirchenko

Computerese Irregular Verb Conjugation:
     I have preferences.
     You have biases.
     He/She has prejudices.
--



Fri, 21 Jun 2002 03:00:00 GMT  
 Counting parameters

Quote:

> How can I count the number of parameters passed to a function that
> accepts a variable number of parameters (C calling convention)?

> Parameters are pushed on the stack from right to left... correct?

That's entirely implementation-dependent.  There may not even be a
stack.

Quote:
> Isn't there some kind of calculation between the current stack pointer
> and the saved base pointer than I can use to figure out how many
> parameters were passed?

Quick answer: No.  (There may be an implementation-specific technique,
but using such a technique is neither wise nor necessary.)

Each function that takes a variable number of parameters must have a
convention for specifying the number and type(s) of the parameters.
If all the parameters are of the same type, you can use a sentinel
value to mark the end of the parameter list; for example, the Unix
execl() function uses a final NULL pointer.  Or one of the initial
argument can be a count of the remaining arguments, though this is
error-prone if you change the call later.  The *printf() functions use
the format string to specify the number and types of the remaining
arguments.

--

San Diego Supercomputer Center           <*>  <http://www.sdsc.edu/~kst>
Welcome to the last year of the 20th century.
--



Fri, 21 Jun 2002 03:00:00 GMT  
 Counting parameters

Navarro) wrote in comp.lang.c.moderated:

Quote:
> How can I count the number of parameters passed to a function that
> accepts a variable number of parameters (C calling convention)?

> Parameters are pushed on the stack from right to left... correct?

> Isn't there some kind of calculation between the current stack pointer
> and the saved base pointer than I can use to figure out how many
> parameters were passed?

> --Dave

The answers in the Borland specific groups could well be different,
but you asked in comp.lang.c.moderated which discusses the ANSI/ISO
standard language, not specific compiler implementations.

The C language does not define or require a stack, stack pointer, or
base pointer.  These mechanisms might be used in the low level
implementation of a particular compiler, or they might not.  Nor does
the language itself specify that parameters are "pushed" on the
"stack" (again, no stack is required) in any particular order.

The language does provide a standard method for accessing the
arguments of a varargs function.  Note that all varargs functions
require at least one fixed argument, and you can define one of the
fixed arguments to contain information about the number and types of
the other arguments, the same way that printf() gets this information
from conversion specifiers in its required first argument, the format
string.

Once you know the number and types of the variable arguments, the
va_arg macros defined in <stdarg.h> allow you to access them in a
standard and completely portable way.

Jack Klein
--
Home: http://jackklein.home.att.net
--



Fri, 21 Jun 2002 03:00:00 GMT  
 Counting parameters

Quote:
Navarro) writes:
>How can I count the number of parameters passed to a function that
>accepts a variable number of parameters (C calling convention)?

The program receiving the variable parameter list must be capable of
determining how many are present.  printf does this by counting the number of
format specifiers in the format string.  (printf also uses the format specifier
to determine the type of parameter to pull.)  Other techniques include a count
as the first parameter or a special value (such as NULL, 0, or -1) as the last
value.
--



Fri, 21 Jun 2002 03:00:00 GMT  
 Counting parameters
Hm?
How does a program work without a stack?
Where are the variables located if there is
no stack? This is confusing!

Felix Reuter
--



Sat, 22 Jun 2002 03:00:00 GMT  
 Counting parameters

Quote:


> > How can I count the number of parameters passed to a function
> that
> > accepts a variable number of parameters (C calling convention)?

> > Parameters are pushed on the stack from right to left... correct?
> That's entirely implementation-dependent.  There may not even be a
> stack.
> > Isn't there some kind of calculation between the current stack
> pointer
> > and the saved base pointer than I can use to figure out how many
> > parameters were passed?
> Quick answer: No.  (There may be an implementation-specific
> technique,
> but using such a technique is neither wise nor necessary.)
> Each function that takes a variable number of parameters must have
> a
> convention for specifying the number and type(s) of the parameters.
> If all the parameters are of the same type, you can use a sentinel
> value to mark the end of the parameter list; for example, the Unix
> execl() function uses a final NULL pointer.  Or one of the initial
> argument can be a count of the remaining arguments, though this is
> error-prone if you change the call later.  The *printf() functions
> use
> the format string to specify the number and types of the remaining
> arguments.
> --

> <http://www.ghoti.net/~kst>
> San Diego Supercomputer Center           <*>
> <http://www.sdsc.edu/~kst>
> Welcome to the last year of the 20th century.
> --


I think you want to declare your func constructs as one pointer in a
stacked array then count. YES!! YOU CAN STACK FOR THOSE NON-BELIEVERS
OUT THERE.

watch and learn

/* +++Date last modified: 05-DEC-1999 */

/*
=======================================================================
    STACK.c     Stack manager.
                MegaZoid_II.

                v0.25  99-05-03  Public Domain.

    Many times I wanted to have one or more stacks for the program I was
    working on. Sometimes I did without -- especially on Quick and Dirty
    utilities. At other times I cobbled up something that more or less
    seemed to work. Crashes were common ...
    So I decided to take the time to do something about it.
    This is the result.

 -  The Stack system is based on dynamic arrays: automatically growing
    the stacks when needed. The growing is done in steps of 16 items.
    This reduces the number of required memory reallocations (and
    therefore the number of allocation failures).
 -  Stack shrinking is intentionally not implemented.
 -  ItemSizes larger than 2kB are not supported: the minimum of initial
    StackItems per stack is currently 32.
    An assert (debug version) limits ItemSizes: <= 1kB and >= 2 Bytes.
    For large data items a separate 'user' module is probably sensible.
    StackUnpop is added to take a look at info, especially size info so
    an appropriate amount of memory can be allocated by the user.
 -  A certain amount of redundancy is provided to enable integrity
checks
    for use in programs with 'wild pointer' problems.
 -  Compile with NDEBUG defined for a 'production' version.
    Compile with NDEBUG _not_ defined for a debug version.
 -  Some functions benefit by using the compilers optimizer.
    Especially 'Common Sub-expression Optimizations'.
 -  Some items should be unsigned in stead of int. Not a real problem.
    Detected by checking the appropriateness and ranges of types.
 -  In some places an int is cast to unsigned, then tested for a 'large'
    value including 'negative' values. This may be non-portable.
 -  Not checked for potential alignment problems. I don't think there
are.
___--------------------------------------------------------------------
*/

#include <stdlib.h>
#include <string.h>           /* memcpy() */
#include <assert.h>           /* debugging */
#include "stack.h"
#include "stk_defs.h"         /* MALLOC, CALLOC, FREE (re-)definitions
*/
                              /* and other debugging re-def's with a  
*/
                              /* special debugging version.            
*/

#define MEMORY          -1    /* Preparations/replacements for GP Error
*/
#define Error(x)        (x)   /* manager. Error may terminate program.
*/

#define STACK_GROWTH    16

struct StackHead
{
    char * base ;        /* base address for the stack (char * because
*/
                         /*     adding offset to void * doesn't work.)
*/
    unsigned offset ;    /* offset of data from base in bytes          
*/
    int top ;            /* offset of data from base in items          
*/
    int itemsize ;       /* itemsize * top should equal to offset      
*/
    int max ;            /* max < top is an error                      
*/
    int underflow ;      /* flag. Incremented when Pops exceed Pushes.
*/

Quote:
};

/*  --- local data and prototypes -------------------------------------
*/

static struct StackHead * StackArray ; /* initialised: StackSystemInit
*/
                                       /* modified by: StackCreate    
*/
static int StackCount ;                /* same. Used by management only
*/
static int StackInit( int Stack, int Itemsize );

/* ---- Management operations -----------------------------------------
*/

int StackSystemInit( int StackCountAdditional )
{
    assert( (unsigned) StackCountAdditional <= 20 );
                 /* negative is logic error (cast => neg. is large int)
*/
                 /* higher than 20 is ridiculous for an initial setup  
*/

    StackCountAdditional += STACK_COUNT_DEFAULT ;

    /* Create and initialize stack 'descriptor' array. A zero value
       for all bytes of a pointer is assumed to be a NULL pointer.
    */
    StackArray = CALLOC( StackCountAdditional, struct StackHead );
    if( NULL == StackArray )
    {
        return Error( MEMORY );
    }

    /* Initialize each default stack.
    */
    if( StackInit( STACK_INT, sizeof( int )))
    {
        return Error( MEMORY );
    }

    if( StackInit( STACK_LONG, sizeof( long )))
    {
        return Error( MEMORY );
    }

    if( StackInit( STACK_PTRS, sizeof( char * )))
    {
        return Error( MEMORY );
    }

    if( StackInit( STACK_FAR_PTRS, sizeof( char FAR * )))
    {
        return Error( MEMORY );
    }

    StackCount = StackCountAdditional ;
    return StackCount ;

Quote:
}

static int StackInit( int Stack, int Itemsize )
{
    StackArray[ Stack ].itemsize  = Itemsize ;
    StackArray[ Stack ].max       = STACK_GROWTH * 2 ;
    StackArray[ Stack ].top       = 0 ;
    StackArray[ Stack ].offset    = 0 ;
    StackArray[ Stack ].underflow = 0 ;

    StackArray[ Stack ].base = MALLOC( STACK_GROWTH *2 * Itemsize, char
);

    if( NULL == StackArray[ Stack ].base )
    {
        return MEMORY ;
    }

    return NO_PROBLEMS ;

Quote:
}

int StackCreate( int ItemSize )
{
    int Stack ;

    assert( (unsigned) ItemSize-2 <= 1022 );
                     /* Not too small, too large or negative please !!!
*/

    /* Look for empty slot
    */
    for( Stack = 0; Stack < StackCount; Stack++ )
    {
        if( NULL == StackArray[ Stack ].base )
            break;
    }

    /*  What if NO EMPTY slot ???
    */
    if( Stack == StackCount )
    {
        struct StackHead * tmp ;         /* StackArray expansion needed
*/

        tmp = realloc( StackArray,
                       (StackCount + 1) * sizeof( struct StackHead ));
        if( NULL == tmp )
        {
            return Error( MEMORY );
        }

        StackArray = tmp ;
        StackCount ++ ;
    }

    if( StackInit( Stack, ItemSize ))
    {
        return Error( MEMORY );
    }

    return Stack ;

Quote:
}

void StackDelete( int Stack )
{
    if( StackCheck( Stack ) < STACK_ERRORS )  /* OK if only warning */
    {
        FREE( StackArray[ Stack ].base );
        StackArray[ Stack ].base = NULL ;
    }
    return ;

Quote:
}

int StackAdapt( int Stack, int Free )
{
   assert( (unsigned) Stack < StackCount );    /* validate stack number
*/

   assert( (unsigned) Free <= 4 * STACK_GROWTH );
                       /* Negative and large numbers are ridiculous ...
*/
                       /* assuming casted negative int = large unsigned
*/

   while( StackArray[ Stack ].top + Free >= StackArray[ Stack ].max )
   {
        char * tmp ;    /* resize Stack in steps */

        tmp = realloc( StackArray[ Stack ].base,
                       StackArray[ Stack ].itemsize
                        * (StackArray[ Stack ].max + STACK_GROWTH ));
        if( NULL == tmp )
        {
            return MEMORY ;
        }

        StackArray[ Stack ].max += STACK_GROWTH ;
        StackArray[ Stack ].base = tmp;
   }

   return NO_PROBLEMS ;

Quote:
}

int StackCheck( int Stack )      /* Check for possible problems in more
*/
{                                /* or less decreasing severity        
*/
    if( (unsigned) Stack >= StackCount )
    {
        return STACK_INV_NUMBER ;
    }

    if( NULL == StackArray[ Stack ].base )
    {
        return STACK_NULL ;
    }

    if( StackArray[ Stack ].top > StackArray[ Stack ].max )
    {
        return STACK_CORRUPT2 ;
    }

    if( StackArray[ Stack ].top * StackArray[ Stack ].itemsize
         != StackArray[ Stack ].offset )
    {
        return STACK_CORRUPT1 ;
    }

    if( 0 != StackArray[ Stack ].underflow )
    {
        StackArray[ Stack ].underflow = 0; /* reset underflow flag */
        return STACK_UNDERFLOW ;
    }

    if( StackArray[ Stack ].top == StackArray[ Stack ].max )
    {
        return STACK_LIMIT_REACHED ;
    }

    if( 0 == StackArray[ Stack ].top )
    {
        return STACK_EMPTY ;
    }

    return NO_PROBLEMS ;

Quote:
}

void StackUnpop( int Stack ) /* Reverse a pop. Data is still present!  
*/
{                            /* very useful for implementing stacks    
*/
                             /* with variable sized items ...          
*/

    if( StackArray[ Stack ].top < StackArray[ Stack ].max )
    {
...

read more »



Sat, 22 Jun 2002 03:00:00 GMT  
 Counting parameters

Quote:

> Hm?
> How does a program work without a stack?
> Where are the variables located if there is
> no stack? This is confusing!

The C language standard doesn't specify where variables are located;
it merely says how they behave.  A stack is probably the most common
way of implementing this, but not the only possible one.

Having said that, I should be more precise about what I mean.  When a
function is called, space is allocated for its local variables.  When
another function is called, more space is allocated for its local
variables.  When a function returns, further attempts to reference any
of its local variables will invoke undefined behavior; presumably the
space is deallocated and made available for other purposes.  In that
sense, there is a "stack", i.e., a first-in-last-out data structure of
some kind.  There's no requirement that this be implemented as a
classical hardware stack, with a contiguous region of memory and a
hardware register used as a stack pointer.  An implementation could do
all the allocation and deallocation from a heap, or in some other
manner.  And, of course, any variables whose addresses are never
computed can be allocated in registers.

Any code that makes too many assumptions about how variables are
allocated will be at best extremely non-portable.

I've redirected followups to comp.lang.c.moderated only.

--

San Diego Supercomputer Center           <*>  <http://www.sdsc.edu/~kst>
Welcome to the last year of the 20th century.
--



Sun, 23 Jun 2002 03:00:00 GMT  
 Counting parameters

Quote:

>Hm?
>How does a program work without a stack?
>Where are the variables located if there is
>no stack? This is confusing!

A language like C requires something that *acts like* a stack
(last-in, first-out) for local variables inside functions.

A linked list, with "add at end with pointer to previous end",
works like a stack:

        struct framelist {
                struct framelist *up;
                pc_type return_address;
                int locals[];   // c99 syntax
        };

        void some_fn(void) {
                // this is generated by the compiler

                struct framelist *mine;
                mine = alloc_frame(size);       // size is computed by compiler
                mine->up = current_frame;
                current_frame = mine;

                {
                // all the code for the function "some_fn" goes here

                // any call to any other fn starts with:
                //      mine->return_address = appropriate_label;
                // so that the other fn can return.
                }

                // function epilogue generated by the compiler
                current_frame = mine->up;
                release_frame(mine);
                jump_to(current_frame->return_address);
                // we never get here
        }

This is in fact how C is sometimes implemented on S/370 (and S/390?)
architectures (IBM mainframes).

On many RISC machines, parameters are passed in registers, rather
than on a stack.  Obviously there is some limit to this: for
instance, on the MIPS, the first four non-FP scalars go in a0
through a3, while on the SPARC, the first six scalars (assuming no
long longs, or V9 and no FP) go in %o0 through %o5.  (On V9, FP
parameters go in the FPU registers, as they always do on the MIPS.)

On the old Pyramid, the first *12* (!) scalars went in tr0 through
tr11.  Like the sparc, these registers were windowed and "became"
pr0 through pr11 in the callee.
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc


--



Sun, 23 Jun 2002 03:00:00 GMT  
 Counting parameters


Quote:
>A language like C requires something that *acts like* a stack
>(last-in, first-out) for local variables inside functions.

Why?  All that is required is that the function behave correctly, you
can make no other assumptions (unless you are referring to a single
object such as an array or struct)

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
--



Sun, 23 Jun 2002 03:00:00 GMT  
 Counting parameters


Quote:
>Hm?
>How does a program work without a stack?
>Where are the variables located if there is
>no stack? This is confusing!

Why, it is only confusing because of your view of how parameter passing
works.  For example the compiler can arrange for the arguments to be
placed somewhere and pass the start of that area to the function being
called.

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
--



Sun, 23 Jun 2002 03:00:00 GMT  
 Counting parameters

Quote:

>Hm?
>How does a program work without a stack?

     The same way it works without a bicycle.  A bicycle isn't
necessary for a program to run and neither is a stack.

Quote:
>Where are the variables located if there is
>no stack? This is confusing!

     Values are stored in memory.  You need different protocols for
accessing them, but that's an implementation detail and <stern
demeanor> we look down on such stuff here (comp.lang.c.moderated)
</stern demeanor>.

Sincerely,

Gene Wirchenko

Computerese Irregular Verb Conjugation:
     I have preferences.
     You have biases.
     He/She has prejudices.
--



Sun, 23 Jun 2002 03:00:00 GMT  
 Counting parameters

Quote:
>Hm?
>How does a program work without a stack?

As far as C goes, this isn't important. It is possible, but the
stacklessness or otherwise of the underlying CPU is simply not exposed
directly to the C programmer. Though, in the same way in which one can
determine 1s- vs 2s-complement calculations, it might be possible to
deduce this information.

Quote:
>Where are the variables located if there is
>no stack? This is confusing!

Somewhere apart from the stack :-) There is no obligation for a CPU to
support a stack -- Acorn's (earlier?) ARM models didn't have an official
one -- and variables can be placed in the heap, in the program image, on
disk, in registers, etc.

--Tom
--



Sun, 23 Jun 2002 03:00:00 GMT  
 
 [ 23 post ]  Go to page: [1] [2]

 Relevant Pages 

1. pCmd->Parameters->Count fails when there's no parameter

2. va_arg and the count of parameters

3. How can i count numbers in an int or count characters in a string in the

4. Differencies in compilation: a[count++]=count;

5. Counting the clock... (counting clock cycles)

6. VC7 does NOT support template-template parameters involving non-type parameters

7. function parameters: default value, optional parameter

8. Parsing application parameters(command line parameters)

9. Input parameters and Output parameters

10. count number in an int & count characters in a string

11. Counting bits set in 32 bit word - Population Count.

12. Form count

 

 
Powered by phpBB® Forum Software