Critique

J

Joe Wright

Mark said:
On Tue, 12 Apr 2005 18:40:28 -0400, in comp.lang.c , Joe Wright
[ snip ]
My problem is that this is fine for tiny programs, with a half-dozen
functions.

But as soon as you get a few lengthy functions, it becomes quite
annoying. And it makes for significant maintenance the second you need
to split the project across multiple files. So my tendency is to start
out as if the program would later become multifile. I even tend to put
all the fn prototypes into a header straight away.

If you really assume multifile at the beginning, then you would have
func.c with your functions, func.h with their prototypes and main.c
which will #include "func.h" and provide the main() function only.
 
A

Alan Balmer

Alan Balmer wrote on 13/04/05 :

Never heard of reusability, test units ?

Hasn't everyone? Never heard of local functions? Must all functions be
reusable? How about the functions you write on top to avoid writing an
extra line? Are they reusable? If so, do you duplicate them in each
translation unit so as to avoid the need for excess prototypes? This
is called "cut and paste" reusability, and is downright dangerous. Or
do you engage in the abhorrent practice of #including executable code?

When functions are reused, I write them in a separate translation
unit, and generate an appropriate header file to describe the user
interface. I don't think I'm alone in this practice.

I'm curious to know how you implement reusable code.
 
A

Alan Balmer

Mark said:
On Tue, 12 Apr 2005 18:40:28 -0400, in comp.lang.c , Joe Wright
[ snip ]
My problem is that this is fine for tiny programs, with a half-dozen
functions.

But as soon as you get a few lengthy functions, it becomes quite
annoying. And it makes for significant maintenance the second you need
to split the project across multiple files. So my tendency is to start
out as if the program would later become multifile. I even tend to put
all the fn prototypes into a header straight away.

If you really assume multifile at the beginning, then you would have
func.c with your functions, func.h with their prototypes and main.c
which will #include "func.h" and provide the main() function only.

The downside to that is that now all functions are global. Also, you
have a plethora of modules with code used by only one program.
 
R

Richard Bos

CBFalconer said:
Since we are no longer using line oriented editors there is no
penalty to be paid for writing main first, and then moving above it
to create the various subroutines.

Yes, there is: it makes reading the code less straightforward, at least
IMO. I don't know about you, but I prefer to have the most high-level
material first, and the more specific parts after that, in any kind of
text, not just code. Thus, code in which main() comes first, followed by
the lower level functions, is more readily understandable by me than the
other way around.

Richard
 
R

Richard Bos

Emmanuel Delahaye said:
The good place for main() is the last function of main.c

First, thank you.
Easy to implement, easy to find and Vulcan-logic.

Ditto, ditto, and legible for humans, not for robots or Skiffy
near-robots.

Richard
 
C

Christopher Benson-Manica

Richard Bos said:
Yes, there is: it makes reading the code less straightforward, at least
IMO. I don't know about you, but I prefer to have the most high-level
material first, and the more specific parts after that, in any kind of
text, not just code. Thus, code in which main() comes first, followed by
the lower level functions, is more readily understandable by me than the
other way around.

It seems to be a matter of religion, to some extent. The general
practice here (and my preference) is to leave main() or its
equivalents until last, with prototypes and definitions preceding it,
FWIW.
 
E

Emmanuel Delahaye

Alan Balmer wrote on 14/04/05 :
When functions are reused, I write them in a separate translation
unit, and generate an appropriate header file to describe the user
interface. I don't think I'm alone in this practice.
Agreed.

I'm curious to know how you implement reusable code.

I was answerwing to "Why should I separate local function, used by no
other program, into
separate source modules?"

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

..sig under repair
 
M

Mark McIntyre

Mark McIntyre wrote:

If you really assume multifile at the beginning, then you would have
func.c with your functions, func.h with their prototypes and main.c
which will #include "func.h" and provide the main() function only.

Except that I never have a file called main.c, and typically the
'main' module contains all the controller code, be it main, menus,
processing loops etc.

Heck, do we need to spend weeks teaching each other how to structure
programmes?
 
M

Mark McIntyre

It seems to be a matter of religion, to some extent. The general
practice here (and my preference) is to leave main() or its
equivalents until last, with prototypes and definitions preceding it,
FWIW.

Grin. I generally start designing at the top, not the bottom, so main
is the first function written.
 
C

Chris Croughton

Yes, there is: it makes reading the code less straightforward, at least
IMO. I don't know about you, but I prefer to have the most high-level
material first, and the more specific parts after that, in any kind of
text, not just code. Thus, code in which main() comes first, followed by
the lower level functions, is more readily understandable by me than the
other way around.

I disagree, I like to see main() last of all with the lowest level at te
top of the file.

It's another "de gustibus" thing, though, there are two ways of looking
at it and no one is going to persuade the other (just as there is no
logical reason why writing from left to right is any better than right
to left -- or downwards and upwards for that matter). It seems that
programmers are about equally split.

Most coding standards I've worked with, though, have a structure like:

include files
macros and enums
typedefs, unions and structs
forward declarations (if any)
static and global data
static functions
public functions

thus going from simple things to more "high level" ones. Whether or not
that is 'better' than some other way, it does seem to be something of an
industry standard, so for many of us that will be te structure we're
used to and therefore more easily understood.

Chris C
 
P

Peter Nilsson

Douglass Adams had the perfect word...

DEVENTER (n) A decision that's very hard to make because so little
depends on it, such as which way to walk around a park.

Mark said:
Grin. I generally start designing at the top, not the bottom, so main
is the first function written.

By rights, you should complete the design before you start coding. So,
it should be immaterial which function you write into source code
first.

But the practice of putting main ahead of other function definitions
does
have one drawback in making code more error prone. Sadly, C90 does not
require a prototype to be in scope on application of a named function.

Whilst C99 requires declarations at least, it still allows programmers
plenty of scope for error...

#include <stdio.h>

unsigned foo();
void bah();

int main()
{
float f;
unsigned i;
...
i = foo(f);
bah(i);
...
}

unsigned foo(float) { ... }
void bah(size_t) { ... }
 
J

Joe Wright

Mark said:
Grin. I generally start designing at the top, not the bottom, so main
is the first function written.

Of course it is. So with me. Then early on in main() I examine the input
parameters (argc/argv stuff) for sanity and if insane, I invoke usage()
to tell the idiot user what to do and exit().

I move my editor's cursor up before main() and define usage() there.

You would move the cursor after main(), define usage(), move the cursor
before main() and declare the prototype. Do I have this right?
 
C

Chris Croughton

Grin. I generally start designing at the top, not the bottom, so main
is the first function written.

main() is always the first function 'written' by me (actually, it's part
of my template for creating a new file, it contains main() with sample
parameter decoding for common options like --help and --version, the
copyright stuff in comments at the top, etc.). That has nothing to do
with where the other functions go, I'm not constrained to add text only
to the bottom of the file, I simply page up to insert the functions,
types etc. that I need.

Chris C
 
E

Emmanuel Delahaye

Chris Croughton wrote on 15/04/05 :
Most coding standards I've worked with, though, have a structure like:

include files
macros and enums
typedefs, unions and structs
forward declarations (if any)
static and global data
static functions
public functions

thus going from simple things to more "high level" ones. Whether or not
that is 'better' than some other way, it does seem to be something of an
industry standard, so for many of us that will be te structure we're
used to and therefore more easily understood.

Agreed. Note that the public global variables (if any) sould be placed
after the functions. It forces the global variables to be declared the
Good Way (in a header included before).

include files
macros and enums
typedefs, unions and structs
forward declarations (if any)
private data (static)
private functions (static)
public functions
public data

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.
 
A

Alan Balmer

Chris Croughton wrote on 15/04/05 :

Agreed. Note that the public global variables (if any) sould be placed
after the functions. It forces the global variables to be declared the
Good Way (in a header included before).
I don't have any problem doing it the Good Way without being forced
;-) Actually, other considerations "force" it anyway - if they're
public, they need to be declared by other modules, and a header is not
only the easy way, but has other obvious advantages.
 
M

Mark McIntyre

Of course it is. So with me. Then early on in main() I examine the input
parameters (argc/argv stuff) for sanity and if insane, I invoke usage()
to tell the idiot user what to do and exit().

I move my editor's cursor up before main() and define usage() there.

You would move the cursor after main(), define usage(), move the cursor
before main() and declare the prototype. Do I have this right?

no, I'd not define usage() at all. Pointless function, you can do it
inline and save moving your cursor at all....
EOD
 
K

Keith Thompson

Mark McIntyre said:
no, I'd not define usage() at all. Pointless function, you can do it
inline and save moving your cursor at all....

It depends on how your program is structured, but I typically have
several calls to usage() for different circumstances (unrecognized
option, invalid argument to an option, bad number of arguments,
explicit "-h" or "-help" option).
 
D

Dave Thompson

How so? If the prototype does not match the definition, it's a
constraint violation. (C90 6.5: "All declarations in the same scope
that refer to the same object or function shall specify compatible
types"; by the rules of 6.5.4.3, any meaningful mismatch between a
prototype that includes a parameter list and the definition of the
corresponding function will produce incompatible function types.)
Very minor nit: if a _prototype-format_ definition is different from,
and hence incompatible with, a prototype separate (forward or
interface) declaration. Formally a K&R1 definition, although it
specifies the parameter types, declares only function of unspecified
arguments which is compatible with any declaration and no diagnostic
is required, although a halfdecent compiler can warn, and should, and
at least GCC does (the versions I can easily check). This was useful
during the transition to C89, since it is easy (and valuable) to make
a separate declaration swap between old-style and prototype with a
macro, but much harder to do so for the definitions.

I have no argument with "declare dependents first" as a matter of
style, but I think its purported advantages are largely subjective.
Presumably you mean "depended-on things" or "dependencies" first, more
colorfully called "bottom-up". I generally like that style, but I
concur it _is_ style and the advantages generally quite modest.

- David.Thompson1 at worldnet.att.net
 

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,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top