coding.html revision 9821041d63289a415ace7e82d4c232ca05f72ce1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync<H2>C Language</H2>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncAn ANSI standard C compiler and library are assumed. Feel free to use any
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncANSI C feature.<P>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync<H2>Warnings</H2>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGiven a reasonable set of things to warn about (e.g. -W -Wall for gcc), the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncgoal is to compile with no warnings.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync<H2>C Source Code</H2>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync<H3>Copyright</H3>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncAll source files should have a copyright. The copyright year(s)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncshould be kept current. The files and the copyright year(s) should be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynclisted in util/copyrights.<P>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync<H3>Line Formatting</H3>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync<H4>Indentation</H4>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUse tabs. Spaces are only allowed when needed to line up a continued
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncexpression. In the following example, spaces used for indentation are
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncindicated with "_":
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync<PRE><CODE>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync printf("this is going to be %s very long %s statement\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync _______"a", "printf");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync</CODE></PRE>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync<H4>Line Length</H4> Lines should not be longer than 80 characters,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynceven if it requires violating the indentation rules to do so.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync<H3>Comments</H3>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncComments should be used anytime they improve the readability of the code.<P>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncComments may be single-line or multiline. A single-line comment should be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncat the end of the line of there is other text on the line, and should start
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncin the same column as other nearby end-of-line comments. The comment
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncshould be at the same indentation level as the text it is referring to.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncMultiline comments should start with "/*" on a line by itself. Subsequent
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynclines should have " *" lined-up with the "*" above. The end of the comment
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncshould be " */" on a line by itself, again with the "*" lined-up with the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncone above. Comments should start with a capital letter and end with a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncperiod.<P>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGood:<P>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync<PRE><CODE>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Private variables.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync static int a /* Description of 'a'. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync static int b /* Description of 'b'. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync static char * c /* Description of 'c'. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync</CODE></PRE>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
The following lint and lint-like comments should be used where appropriate:
<PRE><CODE>
/* ARGSUSED */
/* FALLTHROUGH */
/* NOTREACHED */
/* VARARGS */
</CODE></PRE>
<H3>.h files</H3>
.h files should not rely on other files having been included. .h
files should prevent multiple inclusion. The OS is assumed to prevent
multiple inclusion of its .h files.<P>
.h files that define modules should have a structure like the following:<P>
<PRE><CODE>
/*
* Copyright (C) 1998 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#ifndef ISC_WHATEVER_H
#define ISC_WHATEVER_H 1
/*****
***** Module Info
*****/
/*
* <Module name here>
*
* <One line description here>
*
* <Extended description and notes here>
*
* MP:
* <Information about multiprocessing considerations here, e.g. locking
* requirements>
*
* Reliability:
* <Any reliability concerns should be mentioned here>
*
* Resources:
* <A rough guide to how resources are used by this module>
*
* Security:
* <Any security issues are discussed here>
*
* Standards:
* <Any standards relevant to the module are listed here>
*/
/***
*** Imports
***/
/* <#includes here> */
/***
*** Types
***/
/* <Type definitions here> */
/***
*** Functions
***/
#endif /* ISC_WHATEVER_H */
</CODE></PRE>
<H3>C Source</H3>
<H4>Including Interfaces (.h files)</H4>
The first file to be included must be config.h.
Try to include only necessary files, not everything under the
sun.<P>
Operating-system-specific files should not be included by most modules.<P>
Include UNIX "sys" .h files before ordinary C includes.<P>
<H4>Statements</H4>
There should be at most one statement per line.<P>
Bad:<P>
<PRE><CODE>
if (i > 0) {
printf("yes\n"); i = 0; j = 0;
}
</CODE></PRE>
<H4>Functions</H4>
The use of ANSI C function prototypes is required.<P>
The return type of the function should be listed on a line by itself when
specifying the implementation of the function. The opening curly brace should
occur on the same line as the argument list, unless the argument list is
more than one line long.<P>
Good:<P>
static inline void
f(int i) {
/* whatever */
}
int
g(int i, /* other args here */
int last_argument)
{
return (i * i);
}
</CODE></PRE>
<H4>Curly Braces</H4> Curly Braces do not get their own indentation.
An opening brace does not start a new line. The statements enclosed
by the braces should not be on the same line as the opening or closing
brace. A closing brace should be the only thing on the line, unless
it's part of an else clause.<P>
Good:<P>
<PRE><CODE>
static void
f(int i) {
if (i > 0) {
printf("yes\n");
i = 0;
} else
printf("no\n");
}
</CODE></PRE>
Bad:<P>
<PRE><CODE>
void f(int i)
{
if(i<0){i=0;printf("was negative\n");}
if (i > 0)
{
printf("yes\n");
i = 0;
}}
</CODE></PRE>
<H4>Spaces</H4>
<UL>
<LI>Do put a space between operators like '+', '==', etc.
<LI>Do put a space after ','.
<LI>Do put a space after ';' in a 'for' statement.
<LI>Do put a space after 'return', and also parenthesize the return value.
</UL>
<UL>
<LI>Do not put a space between a variable or function name and '(' or '['.
<LI>Do not put a space immediately after a '(' or immediately before a ')',
unless it improves readability. The same goes for '[' and ']'.
<LI>Do not put a space before '++' or '--' when used in
post-increment/decrement mode, or after them when used in
pre-increment/decrement mode.
<LI>Do not put a space before ';' when terminating a statement or in a 'for'
statement.
<LI>Do not put a space after '*' when used to dereference a pointer, or on
either side of '->'.
<LI>Do not put a space after '~'.
<LI>The '|' operator may either have a space on both sides or it may have no
spaces.
</UL>
<H4>Return Values</H4>
If a function returns a value, it should be cast to (void) if you don't
care what the value is. (Exception for <CODE>printf()</CODE>?)<P>
All error conditions must be handled.<P>
Mixing of error status and valid results within a single type should be
avoided.<P>
Good:
<PRE><CODE>
os_descriptor_t s;
os_result_t result;
result = os_socket_create(AF_INET, SOCK_STREAM, 0, &s);
if (result != OS_R_SUCCESS) {
/* Do something about the error. */
return;
}
</CODE></PRE>
Not so good:
<PRE><CODE>
int s;
/*
* Obviously using interfaces like socket() (below) is allowed
* since otherwise you couldn't call operating system routines; the
* point is not to write more interfaces like them.
*/
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0) {
/* Do something about the error using errno. */
return;
}
</CODE></PRE>
<H4>Integral Types</H4>
Careful thought should be given to whether an integral type should be
signed or unsigned, and to whether a specific size is required. "int"
should be used for generic variables (e.g. iteration counters, array
subscripts). Other than for generic variables, if a negative value isn't
meaningful, the variable should be unsigned. Assignments and
comparisons between signed and unsigned integers should be avoided;
suppressing the warnings with casts is not desireable.<P>
<H4>Casting</H4>
Casting should be avoided when possible.<P>
<H4>Clear Success or Failure</H4>
A function should report success or failure, and do so accurately. It
should never fail silently. Use of Design by Contract can help here.<P>
<H4>Testing Bits</H4>
Bit testing should be as follows:<P>
Good:
<PRE><CODE>
/* Test if flag set. */
if ((flags & FOO) != 0) {
}
/* Test if flag clear. */
if ((flags & BAR) == 0) {
}
/* Test if both flags set. */
if ((flags & (FOO|BAR)) == (FOO|BAR)) {
}
</CODE></PRE>
Bad:
<PRE><CODE>
/* Test if flag set. */
if (flags & FOO) {
}
/* Test if flag clear. */
if (! (flags & BAR)) {
}
</CODE></PRE>
<H4>Pointers</H4>
<H5>Null Pointer</H5>
The null pointer value should be referred to with "NULL", not with "0".
Testing to see whether a pointer is NULL should be explicit.<P>
Good:
<PRE><CODE>
char *c = NULL;
/* ... */
if (c == NULL) {
/* Do something. */
}
</CODE></PRE>
<H5>Invalidating Pointers</H5>
When the data a pointer points to has been freed, or is otherwise no longer
valid, the pointer should be set to NULL unless the pointer is part of a
structure which is itself going to be freed immediately.<P>
Good:
<PRE><CODE>
char *text;
/* text is initalized here. */
free(text);
text = NULL;
</CODE></PRE>
<H4>Testing for Zero or Non-zero</H4>
Explicit testing against zero is required for numeric, non-boolean variables.
<P>
Good:
<PRE><CODE>
int i = 10;
/* ... */
if (i != 0) {
/* Do something. */
}
</CODE></PRE>
Bad:
<PRE><CODE>
int i = 10;
/* ... */
if (i) {
/* Do something. */
}
</CODE></PRE>
<H3>Initialization</H3>
When an object is allocated from the heap, all fields in the object must be
initialized.<P>
<H3>Dead Code Pruning</H3>
Source which becomes obsolete should be removed, not just disabled with
#if 0 ... #endif.<P>