tags:

views:

207

answers:

7

Does anyone have any opinions on not using prototypes unless necessary for functions declared "static". Do you always put them at the top of your translation unit? I tend to but recently I've been thinking about why not rely on the ordering of the functions and in way you can limit some scope of where the function can be called from, potentially forcing yourself to think a little bit more about the scope of the function. I'm still on the side of doing the prototype, but I can see arguments aren't completely baseless for the other side of the fence. I suppose this argument could also be continued on to #define and file scope variables.

+2  A: 

I tend to write functions in Pascal order (i.e., define before use) rather than declaring with prototypes. Especially during development when signatures change frequently, having to maintain two copies of the same information is irritating and potentially flow-breaking.

Greg Bacon
Agreed. A separate declaration and definition break the "single source of truth" rule.
Jay
A: 

You have to have a prototype visible at the point of use in C++, but not necessarily in C. I prefer to always prototype functions anyway in C. There's no good reason not to. A prototyped function definition is sufficient (again, no such thing as an unprototyped function definition in C++) and I don't see anything wrong with having the function defined as close to its point of use as possible (i.e. just above its first use) and relying on this for the prototype.

On the other hand it can be useful to have a set of function declarations to refer to at one point in a file, but even as someone who doesn't use an IDE that automatically indexes function in source that often, it isn't a big issue for me.

Charles Bailey
I'm sort of the same way, a quick grep and jump is usually plenty for me as an emacs user. I'll use etags every now and again when I first inherit a project though. I also find doxygen's ability to index very helpful as well for understanding structure of a new project.
Dude
A: 

I generally follow the "don't repeat yourself" school of thought and declare static functions at the top of the translation unit. I dislike having too many points of edit when I change a function signature.

Reducing the scope of where the function is visible from seems like a secondary consideration to me - if this was particularly important (e.g. if I wanted to ensure people didn't 'abuse' the function) then I'd consider moving it to another translation unit along with the calling code.

HulkHolden
If you declare them at the top of the TU, don't you repeat your self when you subsequently define them? Defining them before use would be less 'repeating yourself', surely?
Charles Bailey
Either way you have ugly dependencies in your code: If you use the "define before use" model, you have to keep an eye on the order of calls/definitions of the function. If you use the other way, you have the obvious duplication of the parameter types. I have to say, i also prefer the other way (first only declaring all of them, and later defining them. Way cleaner in my opinion)
Johannes Schaub - litb
A: 

If you do not write prototype declarations for your static functions, then you have to define them before using them. This is a constraint and, as far as I can tell from my own experience, this is a good constraint: it forces the developer to write code in a logical order, and related functions tend to remain grouped together. With declared prototype on top of the file, the code has more potential to become a tangled mess.

Moreover, the not-pre-declaring rule means that when you must add a prototype (because you have a multi-level recursion) then the prototype tends to stick out as a good marker for a difficult piece of code (i.e. the multi-level recursion).

Thomas Pornin
+4  A: 

I follow the "define before use" rule myself wherever possible (thus my files always read from the bottom up). That way I don't have to worry about keeping declarations and definitions in sync, at least within the same file.

To be pedantic, you're talking about declarations, not prototypes; prototype refers to the syntax of a declaration/definition (i.e., declaring the number and types of parameters in the parameter list). To be clear, the following declaration and definition use prototype syntax:

/**
 * prototype declaration; the number and types of parameters are
 * part of the declaration, so the compiler can do type checking
 * on the function call
 */
double f(int x, int y, double z);
/**
 * prototype definition
 */
double f(int x, int y, double z)
{
  ...
}

whereas the following declaration and definition do not use prototype syntax:

/**
 * non-prototype declaration; the number and types of parameters
 * are not specified, so the compiler can't do any type checking
 * on the function call.
 */
double f();
...
/**
 * non-prototype definition; this is still legal AFAIK, but
 * *very* outdated, and should no longer be used
 */
double f(x, y, z)
  int x;
  int y;
  double z;
{
  ...
}

Whether you define functions before use, or just declare before use and define later, always use prototype syntax.

John Bode
+1 because you don't leave the questioner alone with his confusion around "prototype" and "declaration". Repeating the same mistake like most folks in this thread currently do isn't any good.
Johannes Schaub - litb
Yeah I appreciate the reminder. And I always give types, arguments, and names to my prototypical allocations ;) . I have been doing it for so long I get confused for a moment when I see it done any other way.
Dude
A: 

I like to define my functions by alphabetical order, which helps in finding functions.

A function declaration section at the beginning of the source allows the function definitions to be in any order. I also alphabetize the the declaration section.

Thomas Matthews
Hmmmm, interesting I know a few people who do that with variables as well. I prefer to keep things as close to where they're used as possible, but there's really no use if you declare everything up at the top, because at that point the compiler has total freedom to use that static function whereever located in the body of the file (translation unit). I am used to just doing protocol declarations at the top for static functions and grouping them if there is a logical group. I like c99 allowing you to place variable closer to where they are used.
Dude
I don't alphabetize variables, except in objects. In methods and functions, I declare variables as close as I can to their first usage.
Thomas Matthews
A: 

Note: This answer applies to C++

It seems to me that you believe that using prototypes is considered good practice and not using them some sort of neglect. I remember that my first C++ docent also attached importance to creating prototypes.

However, in the professional world I have never encountered such a rule. Except for the guideline that you should avoid writing the function/method definitions in the header files. But that's mostly to have a clear separation between interface and implementation and also to avoid potential linker errors.

To answer your question: if a function is only needed within a CPP file then it should be static or be in a namespace to avoid conflicts with externals and it doesn't need to have a prototype.

StackedCrooked
I know when static functions should be used, I was just wondering if there was a general consensus on where the prototype declaration lived in the file.
Dude