It's common practice to prefix a function definition in a .C file with comments in a standard format that describe the function, its parameters and inputs/outputs.
Is it common practice to duplicate this information as a prefix to the function prototype in a header .h file. or to not have it in the .c file at all and only in the header file?
TIA
Didn't find your answer? Ask the community — no account required.
M
Meindert Sprang
I'd say, it depends. If I'm writing code for my own products/projects, I place a comment in the C file above each function and not in the header file. To keep it at two places is a source for mistakes because sooner or later, you forget to update one of them.
When the header file is to be delivered as an interface with an object file, I would place it in the header file.
Meindert
D
darkknight
Right.
Have you ever done this or do you have any examples of this being done?
T
toby
As an aside, it seems a sensible policy when using markup for a documentation generator (such as Doxygen[1]); because this documentation is meant to show the 'what' and not the 'how' normally covered by internal comments. Obviously, as Meindert points out, it would be silly to have this in both the header and the source, and since the header would normally be distributed as the API, it's convenient for the documentation ('what') to be integral to it.
Absent a document generator, either way could work, but in my own projects I would tend to use the .c (definition) and do all commenting (internal and external) there, leaving the .h and prototypes free of comments.
Just my .01c. [1]
formatting link
M
Meindert Sprang
file,
No. It's just how I would do it.
Meindert
S
Steve at fivetrees
First, I put public function definitions only in the header file, and private function definitions (all defined static to enforce limited scope) only in the .c file.
Second, I try to ensure the public function definition's usage is obvious.
Third, I consider that the header file, being public, *is* the interface - therefore if I'm being particularly assiduous, I'll include commentary in the header file to document usage. (However I don't duplicate the commentary in the .c file - that's often concerned with "how", rather than "what".)
HTH,
Steve
formatting link
D
darkknight
I assume you mean declarations, not definitions. Function prototypes are not definitions.
So does this mean that for "exported" functions (functions with external linkage), the function prefix description is with the prototype and for non-exported functions the description is with the function definition (implementation) .
How? In my code, identifier names are made as meaningful and descriptive as possible as concisely as possible, regardless of where they appear.
I find that the description that prefixes the function needs to be with the function definition in the .c file because it needs to be referred to when examining the function implementation. e.g. it describes the inputs and pre-conditions - things you need to know when checking the implementation.
For C++ code, I don't recall ever seeing a class definition that included "function description details" within the class definition (which is an interface).
Thanks for the reply.
darkknight
S
Steve at fivetrees
You're right. (I plead insanity due to heavy-duty painkillers.)
Kinda. I tend not to muddy up the function prototypes as such - I tend to include a "howto" in the .h file that explains usage instead.
Yeah, that's what I do. But also good decomposition helps.
Absolutely. See my earlier reply re "how" (the implementation) vs "what" (the interface).
Ah. I was talking about C rather than C++, which I prefer not to use (but that's another story that we've discussed rather a lot here ;)).
Steve
formatting link
P
Peter Bushell
It doesn't happen as often as it should.
That said, if a UML tool is being used to generate the class declaration (as is increasingly happening with C++), that is the place to have the documentation. Then it matters less if it doesn't get through to the .h file.
-- Peter Bushell
formatting link
N
Not Really Me
I have seen this done in a C++ package delivered to us as a linkable library we licensed. It included the library and a set of commented .h files that defined all of the class information.
Scott
J
Jack Klein
On Tue, 27 Sep 2005 18:49:19 +1200, darkknight wrote in comp.arch.embedded:
I work for a large organization where as 10 or so programmers might well be working on a large, complex embedded program. We adopted our current rules about 3 years ago.
First, the application is partitioned into tasks (when there are multi-tasking operating systems) or modules. Each task or module is assigned to a programmer. Each task or module gets its own directory in the top-level source code directory, which contains nothing but directories.
There is a single common include directory where each task/module provides two headers. One header includes the prototypes for all of the functions that are available to be called from other tasks/modules. The other header, which is not particularly relevant here, contains typedefs and possible some macros that other tasks/modules might need to use in calling those exported API functions.
If I am going to call a function in the XYZ task, written by somebody else, there is no way I want or need or should have to look in the xyz directory at the source code to find information about how to call a function xyz exports. So the Doxygen function header block goes in the header file that prototypes the function:
/***************************************************************************/ /** PS_GetValue - This function reads a configuration value owned by * the Persistent Storage subsystem. ** \param token - A token that specifies which value is to be read * (for possible values see description of enum ps_value_token_t). * \param dest - A pointer to a location where the requested * value is to stored * \return error_code_t, OK or BAD_PARAMETER
Since we don't want the information duplicated, there is a much smaller comment block with the definition of the function in a source code file, its main purpose is to indicate the header that includes the prototype and full comment block:
/***************************************************************************/ /** PS_GetValue - see ps_api_calls.h for details
By the way, the 'PS_' prefix in this example indicates that the function is part of the PS module that manages the persistent storage (SPI EEPROM) in this particular application.
An individual task/module often has several different source code files itself, and needs to make function calls between them. So each has one or more internal headers, and the same thing applies here, the full comment is in the header with the prototype, the abbreviated header in the source file mainly to identify which header file contains the prototype and full comment.
Finally, any static functions within a source file are prototyped with the full comment block before any code. Again, the function definition later in the body has the abbreviated block which merely says "see prototype in this file for details".
Of all the various systems I've used at different companies and on different teams over the years, I think this one scales best to C projects with more than one or two programmers involved.
I may need to look at your source code for a code inspection, or to work on it while you're on vacation or have moved on to another project. I should not have to look at your source code to see how to call your function, and what the parameters and return values are.
The header file should be the interface to the function to both the compiler and other programmers.
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
L
Lanarcam
What about this suggestion:
One is not restricted to the use of .h or .c for files extensions. Suppose you have these files, module.c module.h, module.ch, module.hh.
module.h contains the declaration of functions and module.c the implementation as usual.
module.hh contains comments related only to the public interface of module, for instance comments about exported functions and parameters.
module.ch includes module.hh and adds comments related to private implementation. module.h includes module.hh module.c includes module.ch
T
Thad Smith
I also consider the header file as the interface definition. It gets full documentation on use of the public functions. It does not have any private functions or types / constants used only within the definition. If there is a confusion about the operation of a function, it is a strong indication that it wasn't documented properly in the header file.
As as aid to myself, I copy the header comments and declaration into the code file. If I change it one place, I am careful about updating it in the other place. Strictly speaking, this is a violation of the single source definition principle (also called DRY -- Don't Repeat Yourself), but worthwhile for me. It would, of course, be possible to automate copying from one place to the other.
Thad
D
Dan Henry
=== SNIP ===
Yes, I am late to the party, but if there is anyone who is still sober...
I have come across this 2-header model before; that is, one header file with only function prototypes and another header file containing the 'magic goodies' required to utilize those prototyped functions.
I have been searching for (not in a Google way, but rather by asking organizations "why is this in your coding standards?" way), and not yet found, a justification for the 2-header model. Invariably, I find that files including the prototype header end up including the 'other' header. I am eager to learn why the 2-header model is used. Can anybody enlighten me?
-- Dan Henry
M
Mark McDougall
Heh, sounds like a compromise between those that insist that design documentation be included in the source code, and those (like myself) who *detest* code polluted by more than a spattering of comments.
Ever tried maintaining code that consists of twenty-odd 5-line routines interleaved with 2 pages of comments between each function? Or scrolling thru 5 pages of header comments to find a #define value or function prototype? It gets annoying *very* quickly - even with a scroll-wheel!
IMHO Code comments should be restricted to brief 'and this block does this...'-style comments and tricky/subtle/unusual implementation details
- the rest belongs in the (completely separate) design document.
Regards, Mark
B
Bo
Years ago when using an Intel compiler for an 80C196KC, I was taught this 'trick' by the Intel support guys. I'm sure that compilers have significantly improved since then and that this method is probably not NEEDed any longer--but I continue to use it for several reasons. The original reason driving this method was that it gave both compiler and linker more visibility into the overall project and thus was able to better optimize and figure out which variables could be overlaid and which couldn't. This became a real issue when you started running out of available RAM on the part.
Here's the synopsis:
all function prototype are in one file: prototype.h all macros, #defines are in one file: defines.h
all globals are in one file: globals.h inside of globals.h at the top:
" #ifdef GENERATING_GLOBALS #define Global #else #define Global extern #endif " All variable in the global.h file are then declared like:
As said earlier, this method is probably not required any longer for overlay/optimization purposes, but I continue to use on small one or two person projects because:
1) want to know if a variable is global? look in globals.h
2) want to know what a function prototype is? look in prototype.h
3) want to know what EISR is defined to be? look in defines.h
It's a super convenient way to know what things are without searching a bunch of h files to find it. I further added to Intel's suggestion by creating a types.h file in which all typedefs, union, and struct definitions reside.
Downsides: any change to any of these three files will cause re-compile/rebuild of ALL project files. does not work well for large or multi-person projects
Hope this helps answer your question....
Bo
A
Alan Balmer
You've lost me. It seems that you are creating a situation where you
*must* search a bunch of files to find it. If all the above were in one file, there's only one place to look. In fact, most things would be identifiable just by grepping the file for the name.
Al Balmer
Balmer Consulting
removebalmerconsultingthis@att.net
A
Alan Balmer
I often heavily document the function prototypes in the header file. The intent is that a user need look only in one place for all the information needed to use the functions prototyped.
Most editors I use will find such very quickly without using a scroll wheel, or even a mouse.
Al Balmer
Balmer Consulting
removebalmerconsultingthis@att.net
T
Thad Smith
You could do that, of course. For me, that would separate the comments and relevant code too much (.c and .ch). The way I use interface .h files, all the interface details are in that one file, with the function comments just above the associated declaration, thus keeping the human- and machine-readable interface details together. It helps me keep them in sync. If you are going to have external documentation, you might as well make it a text or word processor file.
A
Albert van der Horst
I prefer this style:
/*******************************/ Find the configuration value from the Persistent Storage subsystem identified by ``token'' and store it at ``dest''. Return OK or BAD_PARAMETER , whatever applies. /*******************************/
I think the function prototype can be taken for granted. It cannot reasonably be duplicated in the description, so I don't try.
What I try to tell is, I hate descriptions where the action is separated from the objects. It is verbose and if taken litterally, not really watertight. For example, you could get away with always returning ``OK'' and claim that it is within spec.
(OTOH, if there is a general remark about error codes on top of the c-file, you should leave it out of the function description. That would be okay. )
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- like all pyramid schemes -- ultimately falters.
albert@spenarnc.xs4all.nl http://home.hccnet.nl/a.w.m.van.der.horst
Join the Discussion
Have something to add? Share your thoughts — no account required.
Didn't find your answer?
Ask the community — no account required
Report Content
You are reporting this content to the moderators. They will look at it
ASAP.