473,466 Members | 1,324 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

functions that take many arguments...... + extern - what about it?

Hi,

Problem:
========
Some of my output functions are beginning to take pretty many
arguments... I mean.... We're talking about 10-15 arguments :-)

So I thought to myself, perhaps this is beginning to get out of hands if
I continue to put in extra functionality in the (file-writing)
output-functions....

I thought to myself that perhaps I should begin to assemble some of the
2D pointers into some structures and then pass the pointer to the
"container" structure, even though I probably wont be needing all
pointers in the structure. That should get rid of a a few of function
arguments... Or would it be completely acceptable to live with say 20
arguments? As an example... Take this function:

void vtk_output(int nx, int ny, int nz, double *xvalues,
double *yvalues, double *zvalues,
double **temp_array, double **porosities,
double **local_rhocp, double **p_locations,
int show_p_locations, int show_rhocp,
unsigned number_of_interior_cells,
int *output_filestep, int output_direction,
int num_integration, int show_boundary)
I'm passing some integers that either has the value 0 or 1... Perhaps I
should rewrite the program and use some bit-fiddling stuff - using
logical AND / OR for comparing?

The following holds either 0 or 1:

int show_p_locations,
int show_rhocp,
int num_integration,
int show_boundar

And int output_direction is {0, 1, 2 or 3}.

Is there a good way of passing say.... "int control_stuff" where

control_stuff (bit 0) = show_p_locations;
control_stuff (bit 1) = show_rhocp
control_stuff (bit 2) = int num_integration,
control_stuff (bit 3) = int show_boundar
control_stuff (bit 4....7) = reserved for future use...

?

And does any upper limit exists - something about stack overflow or
something to consider, if one passes say 100 arguments (not that I could
think of doing it)?

Also, I never use any "extern" prototypes in my header files. I didn't
get any problems yet so I don't see why the "extern" keyword exists in
the first place? From what I've read various places, this extern keyword
just tells that the definition? is placed in another source file (AFAIR
- something like that)?

Best regards
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Jun 12 '06 #1
16 2292
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:bp************@news.tdc.dk...
Hi,

Problem:
========
Some of my output functions are beginning to take pretty many arguments...
I mean.... We're talking about 10-15 arguments :-)

So I thought to myself, perhaps this is beginning to get out of hands if I
continue to put in extra functionality in the (file-writing)
output-functions....

I thought to myself that perhaps I should begin to assemble some of the 2D
pointers into some structures and then pass the pointer to the "container"
structure, even though I probably wont be needing all pointers in the
structure. That should get rid of a a few of function arguments... Or
would it be completely acceptable to live with say 20 arguments? As an
example... Take this function:

void vtk_output(int nx, int ny, int nz, double *xvalues,
double *yvalues, double *zvalues,
double **temp_array, double **porosities,
double **local_rhocp, double **p_locations,
int show_p_locations, int show_rhocp,
unsigned number_of_interior_cells,
int *output_filestep, int output_direction,
int num_integration, int show_boundary)
I'm passing some integers that either has the value 0 or 1... Perhaps I
should rewrite the program and use some bit-fiddling stuff - using logical
AND / OR for comparing?

The following holds either 0 or 1:

int show_p_locations,
int show_rhocp,
int num_integration,
int show_boundar

And int output_direction is {0, 1, 2 or 3}.

Is there a good way of passing say.... "int control_stuff" where

control_stuff (bit 0) = show_p_locations;
control_stuff (bit 1) = show_rhocp
control_stuff (bit 2) = int num_integration,
control_stuff (bit 3) = int show_boundar
control_stuff (bit 4....7) = reserved for future use...

?

And does any upper limit exists - something about stack overflow or
something to consider, if one passes say 100 arguments (not that I could
think of doing it)?

Also, I never use any "extern" prototypes in my header files. I didn't get
any problems yet so I don't see why the "extern" keyword exists in the
first place? From what I've read various places, this extern keyword just
tells that the definition? is placed in another source file (AFAIR -
something like that)?
If the function is called recursively, then overflow of the stack (automatic
memory) might be a worry.
If your function is passing 100 arguments, then you have written a function
that is literally impossible to debug.
Almost for certain, this is a bad design.

If you are passing 20 arguments, then you have a function that is incredibly
difficult to debug.
Since 80% of the cost of software is maintenance, I think that is what
should really curtail how much stuff we pass into our functions. By making
the functions as small and simple as possible, we make them much easier to
debug and hence to maintain.

There are times when the complexity of the problem requires lots of
parameters to our function. In such cases, we will have to rely on
probabilistic testing + code coverage + endpoint (fencepost) style tests.

So I guess that I am saying that we should limit (as much as possible) the
arguments we pass into a function. But the reason is not due to stack
(we'll call it automatic memory here to avoid problems) but rather is due to
the difficulty of ensuring correctness with a monstrous pile of inputs.

IMO-YMMV.
Best regards
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk

Jun 12 '06 #2
On Mon, 12 Jun 2006 22:52:26 +0200
Martin Jørgensen <un*********@spam.jay.net> wrote:
I thought to myself that perhaps I should begin to assemble some of
the 2D pointers into some structures and then pass the pointer to the
"container" structure, even though I probably wont be needing all
pointers in the structure. That should get rid of a a few of function
arguments... Or would it be completely acceptable to live with say 20
arguments? As an example... Take this function:



void vtk_output(int nx, int ny, int nz, double *xvalues,
double *yvalues, double *zvalues,
double **temp_array, double **porosities,
double **local_rhocp, double **p_locations,
int show_p_locations, int show_rhocp,
unsigned number_of_interior_cells,
int *output_filestep, int output_direction,
int num_integration, int show_boundary)
I think you might have too much being done in one function, you might
want to have more than one output function. Maybe one for each kind of
data. That will probably make thing neater.
And does any upper limit exists - something about stack overflow or
something to consider, if one passes say 100 arguments (not that I
could think of doing it)?

I think C specification specifies a minimum for number of arguments but
not a maximum, although most implementations probably have a limit.
You should check the documentation for the compiler you're using. Of
course, depending on the size of the structures being passed as
parameters you could have memory limitation issues. But you really
shouldn't think about passing that many parameters to a function.
Jun 12 '06 #3
Martin Jørgensen wrote:
Hi,

Problem:
========
Some of my output functions are beginning to take pretty many
arguments... I mean.... We're talking about 10-15 arguments :-)
The only C language issue you've raised is the minimum translation
limit...

* 31 parameters in one function definition
* 31 arguments in one function call

[In C99 it's 127 parameters and arguments.]
So I thought to myself, perhaps this is beginning to get out of hands if
I continue to put in extra functionality in the (file-writing)
output-functions....

I thought to myself that perhaps I should begin to assemble some of the
2D pointers into some structures and then pass the pointer to the
"container" structure,
Or do what most low level file I/O does, use pointers to parameter
blocks.
even though I probably wont be needing all
pointers in the structure. That should get rid of a a few of function
arguments... Or would it be completely acceptable to live with say 20
arguments?
It depends. You're more likely to hit implementation/platform and
general programming
issues than actual language issues.
As an example... Take this function:

void vtk_output(int nx, int ny, int nz, double *xvalues,
double *yvalues, double *zvalues,
double **temp_array, double **porosities,
double **local_rhocp, double **p_locations,
int show_p_locations, int show_rhocp,
unsigned number_of_interior_cells,
int *output_filestep, int output_direction,
int num_integration, int show_boundary)
I'm passing some integers that either has the value 0 or 1... Perhaps I
should rewrite the program and use some bit-fiddling stuff - using
logical AND / OR for comparing?

The following holds either 0 or 1:

int show_p_locations,
int show_rhocp,
int num_integration,
int show_boundar

And int output_direction is {0, 1, 2 or 3}.

Is there a good way of passing say.... "int control_stuff" where

control_stuff (bit 0) = show_p_locations;
control_stuff (bit 1) = show_rhocp
control_stuff (bit 2) = int num_integration,
control_stuff (bit 3) = int show_boundar
control_stuff (bit 4....7) = reserved for future use...

?
Consider the way that open works in POSIX, but it ain't pretty IMNSHO.
And does any upper limit exists - something about stack overflow or
something to consider, if one passes say 100 arguments (not that I could
think of doing it)?
See above.
Also, I never use any "extern" prototypes in my header files.
The lack of extern is incidental, the lack of prototype for such
functions is
criminal. ;-)
I didn't get any problems yet so I don't see why the "extern" keyword exists
in the first place? From what I've read various places, this extern keyword
just tells that the definition? is placed in another source file (AFAIR
- something like that)?


It says that the identifier being delcared has external linkage. It
needn't
be in another source file per se. [With headers, it's not always clear
what
'another source file' means since the header itself is usually another
source
file!]

It's basically redundant, but not quite as redundant as 'auto'.

--
Peter

Jun 12 '06 #4
On Mon, 12 Jun 2006 22:52:26 +0200, Martin Jørgensen
<un*********@spam.jay.net> wrote:
Hi,

Problem:
========
Some of my output functions are beginning to take pretty many
arguments... I mean.... We're talking about 10-15 arguments :-)

So I thought to myself, perhaps this is beginning to get out of hands if
I continue to put in extra functionality in the (file-writing)
output-functions....

I thought to myself that perhaps I should begin to assemble some of the
2D pointers into some structures and then pass the pointer to the
"container" structure, even though I probably wont be needing all
pointers in the structure.


All this would indicate to me that it's time to re-think the design.
--
Al Balmer
Sun City, AZ
Jun 13 '06 #5
Dann Corbit wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:bp************@news.tdc.dk... -snip-
If you are passing 20 arguments, then you have a function that is incredibly
difficult to debug.
Since 80% of the cost of software is maintenance, I think that is what
should really curtail how much stuff we pass into our functions. By making
the functions as small and simple as possible, we make them much easier to
debug and hence to maintain.
Inside the function, it then calls other functions so the problem is
split up into smaller pieces...
There are times when the complexity of the problem requires lots of
parameters to our function. In such cases, we will have to rely on
probabilistic testing + code coverage + endpoint (fencepost) style tests.
How is that done?
So I guess that I am saying that we should limit (as much as possible) the
arguments we pass into a function. But the reason is not due to stack
(we'll call it automatic memory here to avoid problems) but rather is due to
the difficulty of ensuring correctness with a monstrous pile of inputs.


Ok.

Best regards
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Jun 13 '06 #6
Rafael Almeida wrote:
On Mon, 12 Jun 2006 22:52:26 +0200
Martin Jørgensen <un*********@spam.jay.net> wrote:

I thought to myself that perhaps I should begin to assemble some of
the 2D pointers into some structures and then pass the pointer to the
"container" structure, even though I probably wont be needing all
pointers in the structure. That should get rid of a a few of function
arguments... Or would it be completely acceptable to live with say 20
arguments? As an example... Take this function:

void vtk_output(int nx, int ny, int nz, double *xvalues,
double *yvalues, double *zvalues,
double **temp_array, double **porosities,
double **local_rhocp, double **p_locations,
int show_p_locations, int show_rhocp,
unsigned number_of_interior_cells,
int *output_filestep, int output_direction,
int num_integration, int show_boundary)


I think you might have too much being done in one function, you might
want to have more than one output function. Maybe one for each kind of
data. That will probably make thing neater.


But it should all be written to the same file.... Hmm... But ok, good
point. Could probably be done. I just pass in FILE *fp as argument to
each sub-function.
And does any upper limit exists - something about stack overflow or
something to consider, if one passes say 100 arguments (not that I
could think of doing it)?


I think C specification specifies a minimum for number of arguments but
not a maximum, although most implementations probably have a limit.
You should check the documentation for the compiler you're using. Of
course, depending on the size of the structures being passed as
parameters you could have memory limitation issues. But you really
shouldn't think about passing that many parameters to a function.


Do you mean it's a compiler issue if the number of arguments are too many?
Best regards
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Jun 13 '06 #7
Martin Jørgensen wrote:
.... snip ...
Do you mean it's a compiler issue if the number of arguments are
too many?


Not usually (see your compiler docs), but it is a human interface
problem. Look up the rule of 7.

--
Some informative links:
news:news.announce.newusers
http://www.geocities.com/nnqweb/
http://www.catb.org/~esr/faqs/smart-questions.html
http://www.caliburn.nl/topposting.html
http://www.netmeister.org/news/learn2quote.html
Jun 13 '06 #8
Martin Jørgensen wrote:
Some of my output functions are beginning to take pretty many
arguments... I mean.... We're talking about 10-15 arguments :-)


I'd say that was about 10 too many, just on general principles.

--
Chris "seeker" Dollin
"We did not have time to find out everything we wanted to know." /A Clash of Cymbals/

Jun 13 '06 #9

Martin Jørgensen wrote:
Hi,

Problem:
========
Some of my output functions are beginning to take pretty many
arguments... I mean.... We're talking about 10-15 arguments :-)

So I thought to myself, perhaps this is beginning to get out of hands if
I continue to put in extra functionality in the (file-writing)
output-functions....

I thought to myself that perhaps I should begin to assemble some of the
2D pointers into some structures and then pass the pointer to the
"container" structure, even though I probably wont be needing all
pointers in the structure. That should get rid of a a few of function
arguments... Or would it be completely acceptable to live with say 20
arguments?


As with everything else in software, the answer is "it depends."

Don't arbitrarily group items together that don't otherwise form a
logical aggregate. Anything that *does* form a logical aggregate
should be grouped together, but that should be true for the entire
design, not just for an individual function call. For example, I have
no idea what xvalues, yvalues, and zvalues represent in your code, but
if they're coordinates in 3-space, then they could be grouped together
as a "position" aggregate (although instead of a struct of arrays,
you'd use an array of structs, with each struct containing a single {x,
y, z} value).

Similarly, you could group all your flags in another aggregate type
("output_flags") or some such, since they're all logically related
(together they determine the format of your output). You could use a
bitmask for this, but personally I think using a struct is more
straightforward.

If you find that you have twenty arguments that aren't logically
connected except for the fact that this particular function uses them,
then you really do need to rethink your design. However, it does
occasionally happen that you just wind up with functions with large
parameter lists; in those cases, the best thing to do is just document
the hell out of everything.

[snip remainder]

Jun 13 '06 #10
Peter Nilsson wrote:
Martin Jørgensen wrote:
Hi,

Problem:
========
Some of my output functions are beginning to take pretty many
arguments... I mean.... We're talking about 10-15 arguments :-)

The only C language issue you've raised is the minimum translation
limit...

* 31 parameters in one function definition
* 31 arguments in one function call

[In C99 it's 127 parameters and arguments.]


Don't you mean "the maximum limit"?
So I thought to myself, perhaps this is beginning to get out of hands if
I continue to put in extra functionality in the (file-writing)
output-functions....

I thought to myself that perhaps I should begin to assemble some of the
2D pointers into some structures and then pass the pointer to the
"container" structure,

Or do what most low level file I/O does, use pointers to parameter
blocks.


Exactly what I was considering. Then I would have to rewrite a lot, but
that's okay...
even though I probably wont be needing all
pointers in the structure. That should get rid of a a few of function
arguments... Or would it be completely acceptable to live with say 20
arguments?

It depends. You're more likely to hit implementation/platform and
general programming
issues than actual language issues.


How do I know if (as an example) 20 arguments would be too much.

Compiler error? Program crash? Unexpected behaviour? Something else?
As an example... Take this function:

void vtk_output(int nx, int ny, int nz, double *xvalues,
double *yvalues, double *zvalues,
double **temp_array, double **porosities,
double **local_rhocp, double **p_locations,
int show_p_locations, int show_rhocp,
unsigned number_of_interior_cells,
int *output_filestep, int output_direction,
int num_integration, int show_boundary)
I'm passing some integers that either has the value 0 or 1... Perhaps I
should rewrite the program and use some bit-fiddling stuff - using
logical AND / OR for comparing?

The following holds either 0 or 1:

int show_p_locations,
int show_rhocp,
int num_integration,
int show_boundar

And int output_direction is {0, 1, 2 or 3}.

Is there a good way of passing say.... "int control_stuff" where

control_stuff (bit 0) = show_p_locations;
control_stuff (bit 1) = show_rhocp
control_stuff (bit 2) = int num_integration,
control_stuff (bit 3) = int show_boundar
control_stuff (bit 4....7) = reserved for future use...

?

Consider the way that open works in POSIX, but it ain't pretty IMNSHO.


I have no idea about where to find out about that and I don't really
know what POSIX is (ok, I just googled and found out that it's an
abbreviation: Portable Operating System Interface.... + A family of
open system standards based on Unix. Bash is concerned with POSIX
1003.2....)
And does any upper limit exists - something about stack overflow or
something to consider, if one passes say 100 arguments (not that I could
think of doing it)?

See above.

Also, I never use any "extern" prototypes in my header files.

The lack of extern is incidental, the lack of prototype for such
functions is
criminal. ;-)


I have prototypes in my header files. They're just not "extern"...
I didn't get any problems yet so I don't see why the "extern" keyword exists
in the first place? From what I've read various places, this extern keyword
just tells that the definition? is placed in another source file (AFAIR
- something like that)?

It says that the identifier being delcared has external linkage. It
needn't
be in another source file per se. [With headers, it's not always clear
what
'another source file' means since the header itself is usually another
source
file!]

It's basically redundant, but not quite as redundant as 'auto'.


Why do you have the "extern" keyword in front of the prototypes when it
seems unnecessary?
Best regards
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Jun 13 '06 #11
John Bode wrote:
Martin Jørgensen wrote: -snip-
no idea what xvalues, yvalues, and zvalues represent in your code, but
if they're coordinates in 3-space, then they could be grouped together
as a "position" aggregate (although instead of a struct of arrays,
you'd use an array of structs, with each struct containing a single {x,
y, z} value).
Ok, thanks. Gave me something to think about.
Similarly, you could group all your flags in another aggregate type
("output_flags") or some such, since they're all logically related
(together they determine the format of your output). You could use a
bitmask for this, but personally I think using a struct is more
straightforward.
Agreed.
If you find that you have twenty arguments that aren't logically
connected except for the fact that this particular function uses them,
then you really do need to rethink your design. However, it does
occasionally happen that you just wind up with functions with large
parameter lists; in those cases, the best thing to do is just document
the hell out of everything.


I think I've come to a conclusion... If it grows much more, I could
probably rewrite the code and move it into main() where it could see
anything (all variables) instead of getting all kinds of parameters from
main(). It's just that in the beginning this function didn't took many
parameters... And then it growed... And growed... And growed :-)
Best regards
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Jun 13 '06 #12
Martin Jørgensen <un*********@spam.jay.net> writes:
Peter Nilsson wrote:
Martin Jørgensen wrote:
Problem:
========
Some of my output functions are beginning to take pretty many
arguments... I mean.... We're talking about 10-15 arguments :-)

The only C language issue you've raised is the minimum translation
limit...
* 31 parameters in one function definition
* 31 arguments in one function call
[In C99 it's 127 parameters and arguments.]


Don't you mean "the maximum limit"?


It's actually the minimum maximum limit. Each implementation is
allowed to impose a maximum limit on the number of parameters in a
function definition. In C90, that maximum limit must be *at least*
31; in C99, it must be at least 127. Implementations may, and
commonly do, impose a higher limit, or no fixed limit at all.

[...]
even though I probably wont be needing all
pointers in the structure. That should get rid of a a few of function
arguments... Or would it be completely acceptable to live with say 20
arguments?

It depends. You're more likely to hit implementation/platform and
general programming
issues than actual language issues.


How do I know if (as an example) 20 arguments would be too much.

Compiler error? Program crash? Unexpected behaviour? Something else?


Confusion. Your compiler will never give you any problems with up to
31 arguments, but you'll find it impossible to keep track of things
yourself long before that.

[...]

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jun 13 '06 #13
Martin Jørgensen schrieb:
Peter Nilsson wrote:
Martin Jørgensen wrote:
Hi,

Problem:
========
Some of my output functions are beginning to take pretty many
arguments... I mean.... We're talking about 10-15 arguments :-)


The only C language issue you've raised is the minimum translation
limit...

* 31 parameters in one function definition
* 31 arguments in one function call

[In C99 it's 127 parameters and arguments.]


Don't you mean "the maximum limit"?


No. This is the minimal value that your implementation may take as
maximum, i.e. it is allowed to "throw up" at 32 parameters/arguments
but it may as well accept up to 12345 or whatever strikes its fancy.

<snip>
even though I probably wont be needing all
pointers in the structure. That should get rid of a a few of function
arguments... Or would it be completely acceptable to live with say 20
arguments?


It depends. You're more likely to hit implementation/platform and
general programming
issues than actual language issues.


How do I know if (as an example) 20 arguments would be too much.

Compiler error? Program crash? Unexpected behaviour? Something else?


Your implementation _must_ document its actual limits if it is
a conforming implementation of some sort.
The above minimum translation limits let you know that you may
have up to 31 arguments without having to worry -- above that,
you have to look at your implementation's documentation.

As an example... Take this function:

void vtk_output(int nx, int ny, int nz, double *xvalues,
double *yvalues, double *zvalues,
double **temp_array, double **porosities,
double **local_rhocp, double **p_locations,
int show_p_locations, int show_rhocp,
unsigned number_of_interior_cells,
int *output_filestep, int output_direction,
int num_integration, int show_boundary)
I'm passing some integers that either has the value 0 or 1... Perhaps I
should rewrite the program and use some bit-fiddling stuff - using
logical AND / OR for comparing?

The following holds either 0 or 1:

int show_p_locations,
int show_rhocp,
int num_integration,
int show_boundar

And int output_direction is {0, 1, 2 or 3}.

Is there a good way of passing say.... "int control_stuff" where

control_stuff (bit 0) = show_p_locations;
control_stuff (bit 1) = show_rhocp
control_stuff (bit 2) = int num_integration,
control_stuff (bit 3) = int show_boundar
control_stuff (bit 4....7) = reserved for future use...

? <snip>

The above can easily be rewritten to
void vtk_output(struct valueTupel *values,
double **temp_array, double **porosities,
double **local_rhocp, double **p_locations,
unsigned number_of_interior_cells,
int *output_filestep, struct vtk_out_flags *flags)

where
struct valueTupel {
int num;
double *value;
};
and where the "directions" of values can be accessed by, say
enum { X_, Y_, Z_ };
and where
struct vtk_out_flags {
unsigned int show_p_locations: 1;
unsigned int show_p_rhocp: 1;
unsigned int num_integration: 1;
unsigned int show_boundar: 1;
unsigned int output_direction: 2;
};
However, this is just grouping what you have told us about/
what is obvious.
Try to group parameters using struct by the following criteria:
- belong logically together (like nx+xvalues); example:
it is unclear with which number(s) the double ** parameters are
corresponding but if it is always the same, you can group the
numbers and the double ** parameters
- are passed together to functions called from vtk_output().
Say you pass on output_filestep and number_.... and p_locations,
then group them.
If this does not bring you below 5 to 7 parameters, consider a
redesign of your programme in earnest.

Also, I never use any "extern" prototypes in my header files.


The lack of extern is incidental, the lack of prototype for such
functions is
criminal. ;-)


I have prototypes in my header files. They're just not "extern"...
I didn't get any problems yet so I don't see why the "extern" keyword
exists
in the first place? From what I've read various places, this extern
keyword
just tells that the definition? is placed in another source file (AFAIR
- something like that)?


It says that the identifier being delcared has external linkage. It
needn't
be in another source file per se. [With headers, it's not always clear
what
'another source file' means since the header itself is usually another
source
file!]

It's basically redundant, but not quite as redundant as 'auto'.


Why do you have the "extern" keyword in front of the prototypes when it
seems unnecessary?


Historic reasons / parallel use to variable declarations.

For one thing, you can use the keyword to make clear that you thought
about making the functions "static" (internal linkage) but decided to
make them "extern"... :-)
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Jun 13 '06 #14

"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
Dann Corbit wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:bp************@news.tdc.dk... -snip-
If you are passing 20 arguments, then you have a function that is
incredibly difficult to debug.
Since 80% of the cost of software is maintenance, I think that is what
should really curtail how much stuff we pass into our functions. By
making the functions as small and simple as possible, we make them much
easier to debug and hence to maintain.


Inside the function, it then calls other functions so the problem is split
up into smaller pieces...

So if there is a natural hierarchy, express that in structures.
For example you have nx, ny, nz values, and then lists of doubles. It seems
to me that this very easily falls into a group

typedef struct
{
double *x;
double *y;
double *z;
int nx;
int ny;
int nz;
} COORDINATESET;

I am slightly puzzled that nx, ny and nz are different. So put a comment in
the structure definition explaining why this needs to be so.

Similarly the show_ members are probably booleans. It is not usual to pass
these as flags

#define SHOW_PLOCATONS 1
#define SHOW_RHOCP 2
#define SHOW_BOUNDARY 4
#define SHOW_NOTHING 0
That makes the call more humanly-readable, and you only need one parameter.

There are times when the complexity of the problem requires lots of
parameters to our function. In such cases, we will have to rely on
probabilistic testing + code coverage + endpoint (fencepost) style tests.


How is that done?

Code coverage means that you write your tests so that every line of code is
executed at least once. So if you have an exit(0) after a malloc() call, you
artificially manipluate the malloc() to fail at least once at that point.
You can get automatic tools that will help you do this.

Most errors come when data is at the extremes of the range the code is
expected to handle. So for instance if a function takes a string, it is a
good test to pass it an empty string. If it is specified that the string can
be 256 bytes long, pass it one exactly 256 bytes long and see whether
allowance has been made for the null. This applies particularly to loops.
Are the first and the last items in the list processed correctly?

Probabilistic testing means that we haven't shown the program to be
absolutely correct, but we have given enough test cases to make it a
reasonable bet that the program is in fact accurate. It is very difficult to
detect if a function chokes on the input telephoneno = "666". However why
should it? If "666" is hardcoded into the function we should pick it up on a
coverage test. But there just might be some gremlin in there, if it happens
to hash to zero and we have forgotten that zero is a valid slot in the
table, for instance. Even this should have been picked up by an endpoint
test, but you can't expect to get everything right with limited time and
budget.

Jun 13 '06 #15
Malcolm wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
Dann Corbit wrote:
"Martin Jørgensen" <un*********@spam.jay.net> wrote in message
news:bp************@news.tdc.dk...
-snip-

If you are passing 20 arguments, then you have a function that is
incredibly difficult to debug.
Since 80% of the cost of software is maintenance, I think that is what
should really curtail how much stuff we pass into our functions. By
making the functions as small and simple as possible, we make them much
easier to debug and hence to maintain.


Inside the function, it then calls other functions so the problem is split
up into smaller pieces...


So if there is a natural hierarchy, express that in structures.
For example you have nx, ny, nz values, and then lists of doubles. It seems
to me that this very easily falls into a group

typedef struct
{
double *x;
double *y;
double *z;
int nx;
int ny;
int nz;
} COORDINATESET;


Yes, good idea... That would get rid of a lot...
I am slightly puzzled that nx, ny and nz are different. So put a comment in
the structure definition explaining why this needs to be so.
Ok, it's basically just nx = number of cells in the x-direction. double
*x then holds the distances between each element... So inside the
function: for(i=0; i<nx< i++) etc...
Similarly the show_ members are probably booleans. It is not usual to pass
these as flags

#define SHOW_PLOCATONS 1
#define SHOW_RHOCP 2
#define SHOW_BOUNDARY 4
#define SHOW_NOTHING 0
That makes the call more humanly-readable, and you only need one parameter.
I can't do that, because those values are read from an input file
(input.txt).
There are times when the complexity of the problem requires lots of
parameters to our function. In such cases, we will have to rely on
probabilistic testing + code coverage + endpoint (fencepost) style tests.


How is that done?


Code coverage means that you write your tests so that every line of code is
executed at least once. So if you have an exit(0) after a malloc() call, you
artificially manipluate the malloc() to fail at least once at that point.
You can get automatic tools that will help you do this.


So the program terminates before it's supposed to do?
Most errors come when data is at the extremes of the range the code is
expected to handle. So for instance if a function takes a string, it is a
good test to pass it an empty string. If it is specified that the string can
be 256 bytes long, pass it one exactly 256 bytes long and see whether
allowance has been made for the null. This applies particularly to loops.
Are the first and the last items in the list processed correctly?
Ok.
Probabilistic testing means that we haven't shown the program to be
absolutely correct, but we have given enough test cases to make it a
reasonable bet that the program is in fact accurate. It is very difficult to
detect if a function chokes on the input telephoneno = "666". However why
should it? If "666" is hardcoded into the function we should pick it up on a
coverage test. But there just might be some gremlin in there, if it happens
to hash to zero and we have forgotten that zero is a valid slot in the
table, for instance. Even this should have been picked up by an endpoint
test, but you can't expect to get everything right with limited time and
budget.


Agreed... Sounds like my program... I have made a lot of tests, but I
don't really know if there is some "666"-situation, where it gives a
wrong result...
Best regards
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Jun 14 '06 #16
Michael Mair wrote:
Martin Jørgensen schrieb: -snip-
As an example... Take this function:

void vtk_output(int nx, int ny, int nz, double *xvalues,
double *yvalues, double *zvalues,
double **temp_array, double **porosities,
double **local_rhocp, double **p_locations,
int show_p_locations, int show_rhocp,
unsigned number_of_interior_cells,
int *output_filestep, int output_direction,
int num_integration, int show_boundary)
I'm passing some integers that either has the value 0 or 1... Perhaps I
should rewrite the program and use some bit-fiddling stuff - using
logical AND / OR for comparing?

The following holds either 0 or 1:

int show_p_locations,
int show_rhocp,
int num_integration,
int show_boundar

And int output_direction is {0, 1, 2 or 3}.

Is there a good way of passing say.... "int control_stuff" where

control_stuff (bit 0) = show_p_locations;
control_stuff (bit 1) = show_rhocp
control_stuff (bit 2) = int num_integration,
control_stuff (bit 3) = int show_boundar
control_stuff (bit 4....7) = reserved for future use...

?
<snip>

The above can easily be rewritten to
void vtk_output(struct valueTupel *values,
double **temp_array, double **porosities,
double **local_rhocp, double **p_locations,
unsigned number_of_interior_cells,
int *output_filestep, struct vtk_out_flags *flags)

where
struct valueTupel {
int num;
double *value;
};
and where the "directions" of values can be accessed by, say
enum { X_, Y_, Z_ };
and where
struct vtk_out_flags {
unsigned int show_p_locations: 1;
unsigned int show_p_rhocp: 1;
unsigned int num_integration: 1;
unsigned int show_boundar: 1;
unsigned int output_direction: 2;
};
However, this is just grouping what you have told us about/
what is obvious.


Thanks... I'm not so good at using structs, so now I can practice using
them... However I agree it's probably "easy" to change this function
itself... The problem is that I must do a search/replace in my whole
program to modify all these variables in the whole program.... And that
could probably at least take me a couple of days... :-)

But using structs is a better way... I'll try it at some moment...
Try to group parameters using struct by the following criteria:
- belong logically together (like nx+xvalues); example:
it is unclear with which number(s) the double ** parameters are
corresponding but if it is always the same, you can group the
numbers and the double ** parameters
Agreed. Good solution.
- are passed together to functions called from vtk_output().
Say you pass on output_filestep and number_.... and p_locations,
then group them.
If this does not bring you below 5 to 7 parameters, consider a
redesign of your programme in earnest.


It's a good start...

-snip (extern keyword)
Why do you have the "extern" keyword in front of the prototypes when
it seems unnecessary?

Historic reasons / parallel use to variable declarations.

For one thing, you can use the keyword to make clear that you thought
about making the functions "static" (internal linkage) but decided to
make them "extern"... :-)


Ok, thanks.
Best regards
Martin Jørgensen

--
---------------------------------------------------------------------------
Home of Martin Jørgensen - http://www.martinjoergensen.dk
Jun 14 '06 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

99
by: David MacQuigg | last post by:
I'm not getting any feedback on the most important benefit in my proposed "Ideas for Python 3" thread - the unification of methods and functions. Perhaps it was buried among too many other less...
6
by: Melkor Ainur | last post by:
Hello, I'm attempting to build an interpreter for a pascal-like language. Currently, I don't generate any assembly. Instead, I just build an abstract syntax tree representing what I've parsed...
19
by: Ross A. Finlayson | last post by:
Hi, I hope you can help me understand the varargs facility. Say I am programming in ISO C including stdarg.h and I declare a function as so: void log_printf(const char* logfilename, const...
23
by: Timothy Madden | last post by:
Hello all. I program C++ since a lot of time now and I still don't know this simple thing: what's the problem with local functions so they are not part of C++ ? There surely are many people...
7
by: Kenneth Brody | last post by:
The recent thread on "query about main()" got me thinking... As I recall, calling a function with the wrong parameters causes undefined behavior. (These all assume that no prototype of foo()...
8
by: sam_cit | last post by:
Hi Everyone, I read somwhere that c++ compiler does name mangling of functions which is why c source code can't invoke functions from object files that were generated using c++ compiler. Can...
60
by: jacob navia | last post by:
Gnu C features some interesting extensions, among others compound statements that return a value. For instance: ({ int y = foo(); int z; if (y>0) z = y; else z=-y; z; }) A block enclosed by...
14
by: Jess | last post by:
Hello, I learned that there are five kinds of static objects, namely 1. global objects 2. object defined in namespace scope 3. object declared static instead classes 4. objects declared...
5
by: Michael Oswald | last post by:
Hello all, I'm working on a project where I came across some situations, where the GUI library works with normal C callbacks. The code has been implemented by many people, so I came across...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.