Maximum number of function arguments

A

Antriksh Pany

Is there a notion of 'maximum number of function arguments'? As in, is
there such a limit at all by the standard (probably not) or specific
compilers/platforms? Or just the stack size shall determine such a
limit?

Secondly, if a function is required to receive multiple parameters,
what are the pros and cons of using the parameters individually vs
having a container structure for them? Let us assume in this case that
the container structure has to be created only for the sake for
passing parameters to the function, and not otherwise.

Some benefits of using the individual parameters, as they occur to me,
are:
1. No need to have an explicit wrapper structure, which otherwise is
not useful at all.
2. The code to copy parameters to structure members now needn't exist.
3. The first few (usually left to right) parameters (usually two or
three) can be directly copied to and accessed from registers if
needed. This is typically used for most fastcall calling conventions,
and maybe even otherwise.

Benefits of using a wrapper structure:
1. Just the structure pointer needs to be passed, thus possibly saving
on some stack space (although if the original structure was on the
stack anyway (likely), there may not be any savings).
2. The function definition _looks_ neat.
3. Each variable passed is going to be independently aligned on
whatever is the alignment boundary (usually 32 bit), as opposed to a
possibly more efficient memory usage within a structure. But I think
this may not be a cause for concern in most cases.

Overall, I am leaning towards passing individual members as is. I do
not know how correct I am in the assumptions I make above, or if I
have missed something important. Please do make
suggestions/corrections.

- Antriksh

P.S. In case this is already discussed, I apologize. I did some search
but did not find a discussion on the matter. Please do provide the
relevant link(s).
 
G

Giacomo Degli Esposti

Benefits of using a wrapper structure:
1. Just the structure pointer needs to be passed, thus possibly saving
on some stack space (although if the original structure was on the
stack anyway (likely), there may not be any savings).
2. The function definition _looks_ neat.
3. Each variable passed is going to be independently aligned on
whatever is the alignment boundary (usually 32 bit), as opposed to a
possibly more efficient memory usage within a structure. But I think
this may not be a cause for concern in most cases.

4. If you have many function with the same set of parameters, and you
want to add a new parameter, you must change only the struct
definition
and not the function interface. In some cases you can also leave the
function body unchanged:

For example, compare the following code snippets, working
on a "geometric point":
....
void myfunc1( int px, int py, int k, int rx, int *ry );
void myfunc2( int px, int py, int rx, int *ry )
{
myfunc1( px, py, 2, rx, ry );
}
....
and
....
void myfunc1( struct point * p, int k, struct point *r );
void myfunc2( struct point * p, struct point *r )
{
myfunc1( p, 2, r );
}
....
Let's say you want to add also z to your "point". In the first case
you have to
add a new parameter to both function interfaces and handle the new
parameter in
both function bodies. In the second case it is not necessary to change
the function
interfaces and also you need to change only one fun ction body, the
second
still works without changes.

ciao
Giacomo
 
G

Guest

Secondly, if a function is required to receive multiple parameters,
what are the pros and cons of using the parameters individually vs
having a container structure for them? Let us assume in this case that
the container structure has to be created only for the sake for
passing parameters to the function, and not otherwise.

I think that's the wrong question to ask. If you are passing
30 or so parameters (which is about the mini-max allowed by the
standard) you've almost certainly Done Something Wrong. You should be
grouping parameters into structs because they naturally belong
together.
Things like Point or Shape or BaseStation or NetworkConnection.
If you are inventing things that amount to PassedTogether then
you have strayed. IMHO.

Read up on coupling.

Benefits of using a wrapper structure:
1. Just the structure pointer needs to be passed, thus possibly saving
on some stack space (although if the original structure was on the
stack anyway (likely), there may not be any savings).

I remember a programming standard that said "if there's more than
one parameter then put them in a structure for efficiency. A single
parameter is passed in a register the rest use the stack".
[puke]

<snip>

--
Nick Keighley

The beginning of wisdom for a [software engineer] is to recognize the
difference between getting a program to work, and getting it right.
-- M A Jackson, 1975
 
K

Keith Thompson

Richard Heathfield said:
Antriksh Pany said:

The C90 Standard says that a conforming implementation must be able
to support *at least* 31 function arguments. C99 increases this to
127. Thus, there is no imposed maximum. Implementations will
necessarily impose a maximum themselves, but this must be at least
the value quoted (for the relevant standard to which the
implementation conforms).
[...]

Implementations will necessarily impose a maximum, but they needn't
impose a *fixed* maximum, and most (I think) do not. If adding one
more argument causes a program to be rejected, it's probably because
the compiler ran out of memory or some other resource, not because it
ran into a deliberately imposed limit.
 
M

maddoxr

Is there a notion of 'maximum number of function arguments'? As in, is
there such a limit at all by the standard (probably not) or specific
compilers/platforms? Or just the stack size shall determine such a
limit?
- Antriksh

ISO/IEC 9899:1999(E), otherwise known as the C Standard, lilsts in
section 5.2.4.1, "Translation Limits":

- 127 parameters in one function definition
- 127 arguments in one function call

HTH,

- Randy
 
K

Keith Thompson

ISO/IEC 9899:1999(E), otherwise known as the C Standard, lilsts in
section 5.2.4.1, "Translation Limits":

- 127 parameters in one function definition
- 127 arguments in one function call

But it's important to be aware that those are minimum limits.
Compilers are allowed to accept as many parameters or arguments as
they like; they're just not required to accept more than 127.

The minimum limits in C90 are 31, not 127. But if you're getting
close to either limit, you're probably writing unmaintainable code
(which might be ok if it's automatically generated).
 
J

jameskuyper

ISO/IEC 9899:1999(E), otherwise known as the C Standard, lilsts in
section 5.2.4.1, "Translation Limits":

- 127 parameters in one function definition
- 127 arguments in one function call

Keep in mind that these numbers are not the "maximum number of
function arguments", but the minimum number of parameters/arguments
that must appear in one program, provided by the implementors, which
the implementation must translate and execute correctly.

This implies that if the implementation does have hard upper limits,
those limits must be at least 127, but could be higher. However, if
the limits are variable (for instance, they might depend upon the
available memory and the amount of memory required to compile other
features of the program), it doesn't tell you much of anything useful.

That's an example of why the "one program" clause is one of the least
useful clauses in the standard.
 
K

Keith Thompson

jameskuyper said:
Keep in mind that these numbers are not the "maximum number of
function arguments", but the minimum number of parameters/arguments
that must appear in one program, provided by the implementors, which
the implementation must translate and execute correctly.

This implies that if the implementation does have hard upper limits,
those limits must be at least 127, but could be higher. However, if
the limits are variable (for instance, they might depend upon the
available memory and the amount of memory required to compile other
features of the program), it doesn't tell you much of anything useful.
Agreed.

That's an example of why the "one program" clause is one of the least
useful clauses in the standard.

I disagree. The "one program" clause, if taken literally, allows an
implementer to create a conforming implementation that is completely
useless. But the intent is that the most straightforward way to
satisfy the "one program" clause is actually to create a useful
implementation with reasonable capacity limits. And, in practice,
that intent has been achieved; real-world compilers, as far as I've
seen, don't reject programs for using, say, 100 parameters in a
function definition. Without the "one program" clause, some
implementers might have decided to set what they decide are
"reasonable" limits, thinking that *nobody* would ever need that many
parameters.

(I've thought about constructing an instance of that "one program",
and then writing an "implementation" that recognizes it and nothing
else, thereby conforming to the letter of the C standard. I just
haven't gotten around to it.)
 
J

jameskuyper

Keith said:
I disagree. The "one program" clause, if taken literally, allows an
implementer to create a conforming implementation that is completely
useless. But the intent is that the most straightforward way to
satisfy the "one program" clause is actually to create a useful
implementation with reasonable capacity limits. And, in practice,
that intent has been achieved; real-world compilers, as far as I've
seen, don't reject programs for using, say, 100 parameters in a
function definition. ...

I suspect that implementations are commonplace where a strictly
conforming program that places sufficiently severe strain on the
compiler can make the compilation fail as a result of increasing the
number of parameters from 99 to 100.
... Without the "one program" clause, some
implementers might have decided to set what they decide are
"reasonable" limits, thinking that *nobody* would ever need that many
parameters.

I agree - it at least provides guidelines; an it certainly rules out
fixed limits smaller than the limits. That's why its not the "most
useless" clause in the standard - the one that defines "conforming
code" is certainly more useless.
(I've thought about constructing an instance of that "one program",
and then writing an "implementation" that recognizes it and nothing
else, thereby conforming to the letter of the C standard. I just
haven't gotten around to it.)

Me too; but because #error directives need to be handled correctly
even by such an implementation, it requires correctly implementing
essentially all of translation phases 1-4. This in turn implies that
the headers for most of the standard library must be implemented in
some fashion, at least with regard to macro definitions. That in turn
implies that the macros describing intmax_t must be consistent with
the behavior of #if directives. That's a task small enough that I
could imagine actually doing it, complicated enough to be interesting,
but unfortunately large enough that I don't expect to have enough free
time to try it any time soon.
 
L

luserXtrog

I disagree.  The "one program" clause, if taken literally, allows an
implementer to create a conforming implementation that is completely
useless.  But the intent is that the most straightforward way to
satisfy the "one program" clause is actually to create a useful
implementation with reasonable capacity limits.  And, in practice,
that intent has been achieved; real-world compilers, as far as I've
seen, don't reject programs for using, say, 100 parameters in a
function definition.  Without the "one program" clause, some
implementers might have decided to set what they decide are
"reasonable" limits, thinking that *nobody* would ever need that many
parameters.

(I've thought about constructing an instance of that "one program",
and then writing an "implementation" that recognizes it and nothing
else, thereby conforming to the letter of the C standard.  I just
haven't gotten around to it.)

I think it would be more fun to make a virtual ds9000.
Any use of undefined behavior triggers a detailed email
to your mom enumerating all the vile shennanigans it
deduces you must be up to in order to have done such a
thing.
 
C

cr88192

Keith Thompson said:
But it's important to be aware that those are minimum limits.
Compilers are allowed to accept as many parameters or arguments as
they like; they're just not required to accept more than 127.

The minimum limits in C90 are 31, not 127. But if you're getting
close to either limit, you're probably writing unmaintainable code
(which might be ok if it's automatically generated).

I will second this opinion...

as I see it, if one has more than, say, 12 arguments, in most cases probably
something is terribly wrong...

0-4 args is is good
5-6 is ok
7-8 is a little much
9-12 is probably a good upper limit.

more than this, and a struct or array or similar is probably advised...


it is not that the compiler will impose such a limit, rather, this is about
the upper limit of what seams "reasonable" IMO...

now, a few visual examples to demonstrate point:

int foo4(int a, int b, int c, int d);
int foo6(int a, int b, int c, int d, int e, int f);
int foo8(int a, int b, int c, int d, int e, int f, int g, int h);
int foo12(int a, int b, int c, int d, int e, int f, int g, int h, int i, int
j, int k, int l);
int foo16(int a, int b, int c, int d, int e, int f, int g, int h, int i, int
j, int k, int l, int m, int n, int o, int p);

int foo24(int a, int b, int c, int d, int e, int f, int g, int h, int i, int
j, int k, int l, int m, int n, int o, int p,
int ba, int bb, int bc, int bd, int be, int bf, int bg, int bh);
int foo32(int a, int b, int c, int d, int e, int f, int g, int h, int i, int
j, int k, int l, int m, int n, int o, int p,
int ba, int bb, int bc, int bd, int be, int bf, int bg, int bh,
int bi, int bj, int bk, int bl, int bm, int bn, int bo, int bp);

now, in these later examples, does anyone thing this long of args lists is
anywhere within the limits of "good taste?...".
 
B

BartC

cr88192 said:
I will second this opinion...

as I see it, if one has more than, say, 12 arguments, in most cases
probably something is terribly wrong...

0-4 args is is good
5-6 is ok
7-8 is a little much
9-12 is probably a good upper limit.

more than this, and a struct or array or similar is probably advised...
now, a few visual examples to demonstrate point:

int foo4(int a, int b, int c, int d);
int foo6(int a, int b, int c, int d, int e, int f);
int foo8(int a, int b, int c, int d, int e, int f, int g, int h);
int foo12(int a, int b, int c, int d, int e, int f, int g, int h, int i,
int j, int k, int l);
int foo16(int a, int b, int c, int d, int e, int f, int g, int h, int i,
int j, int k, int l, int m, int n, int o, int p);

int foo24(int a, int b, int c, int d, int e, int f, int g, int h, int i,
int j, int k, int l, int m, int n, int o, int p,
int ba, int bb, int bc, int bd, int be, int bf, int bg, int bh);

With 24 params int a to int x would look visually better. C requires every
param has it's own type, otherwise:

int foo24(int a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,z);

wouldn't have looked too bad.

Sometimes this many params can be treated as a list, in this case individual
naming is not needed:

int fooN(int a,...);

which I think is possible in C. Then there is no upper limit except now for
the caller.
int foo32(int a, int b, int c, int d, int e, int f, int g, int h, int i,
int j, int k, int l, int m, int n, int o, int p,
int ba, int bb, int bc, int bd, int be, int bf, int bg, int bh,
int bi, int bj, int bk, int bl, int bm, int bn, int bo, int bp);

now, in these later examples, does anyone thing this long of args lists is
anywhere within the limits of "good taste?...".

If foo32 does a very important job and actually needs that many named (and
perhaps typed) params, then there's nothing wrong with it. Perhaps the
efficiency of passing each param separately is not important. It's not the
language's or compiler's job to impose arbitrary restrictions because of bad
taste or because it thinks it may affect readability.
 
N

Nate Eldredge

BartC said:
With 24 params int a to int x would look visually better.

What does it matter how it looks visually? If the code is written by a
human, to be read by a human, then the parameters should have names that
reflect their meaning. If it's written by a program, to be read only by
the compiler, then it's irrelevant how it looks to anyone.
C requires
every param has it's own type, otherwise:

int foo24(int a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,z);

wouldn't have looked too bad.

This is programming, not graphic design.
Sometimes this many params can be treated as a list, in this case
individual naming is not needed:

int fooN(int a,...);

which I think is possible in C. Then there is no upper limit except
now for the caller.

Except at the expense of giving up type checking, and forcing the
function to do everything via stdarg.
If foo32 does a very important job and actually needs that many named
(and perhaps typed) params, then there's nothing wrong with
it. Perhaps the efficiency of passing each param separately is not
important. It's not the language's or compiler's job to impose
arbitrary restrictions because of bad taste or because it thinks it
may affect readability.

Certainly the compiler shouldn't restrict the programmer in this
respect. But the programmer probably ought to restrict herself.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top