printf("this is going to be %s very long %s statement\n",
_______"a", "printf");
puts("This string got very far to the "
"left and wrapped. ANSI catenation "
"rules will turn this into one "
"long string.");
Comments may be single-line or multiline. A single-line comment should be at the end of the line if there is other text on the line, and should start in the same column as other nearby end-of-line comments. The comment should be at the same indentation level as the text it is referring to. Multiline comments should start with "/*" on a line by itself. Subsequent lines should have " *" lined-up with the "*" above. The end of the comment should be " */" on a line by itself, again with the "*" lined-up with the one above. Comments should start with a capital letter and end with a period.
Good:
/*
* Private variables.
*/
static int a /* Description of 'a'. */
static int b /* Description of 'b'. */
static char * c /* Description of 'c'. */
The following lint and lint-like comments should be used where appropriate:
/* ARGSUSED */
/* FALLTHROUGH */
/* NOTREACHED */
/* VARARGS */
.h files that define modules should have a structure like the
following. Note that
Operating-system-specific files should not be included by most modules.
Include UNIX "sys" .h files before ordinary C includes.
Bad:
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.
Good:
In the function body, local variable declarations are followed by any
Generally speaking, when a control statement (
Good:
Certain functions return values or not depending on the operating
system or even compiler flags; these include
these include
All error conditions must be handled.
Mixing of error status and valid results within a single type should be
avoided.
Good:
Bad (obviously for more than one reason ...):
When a function is designed to return results to the caller by
assigning to caller variables through pointer arguments, it should
perform the assignment only if it succeeds and leave the variables
unmodified if it fails.
Good:
Good:
Good:
Good:
Good:
Bad:
The {module} and {what} segments of the name do not have underscores
separating natural word elements, as demonstrated in
isc_commandline_argument and dns_name_setbuffer above. The {module}
part is usually the same as the basename of the source file, but
sometimes other {module} interfaces appear within one file, such as
dns_label_* interfaces in lib/dns/name.c. However, in the public
libraries the file name must be the same as some module interface
provided by the file; e.g., dns_rbt_* interfaces would not be declared
in a file named redblack.c (in lieu of any other dns_redblack_*
interfaces in the file).
The one notable exception to this naming rule is the interfaces
provided by
Log messages do not start with a capital letter, nor do they end
in a period.
When variable text such as a file name or domain name occurs
as part of an English phrase, it should be enclosed in single
quotes, as in
When the variable text forms a separate phrase, such as when it
separated from the rest of the message by a colon, it can be left
unquoted. E.g.,
Function names, line numbers, memory addresses, and other references
to program internals may be used in debugging messages and in
messages to report programming errors detected at runtime.
They may not be used in messages that indicate errors in the
program's inputs or operation.
Perl 5 is assumed; Perl scripts do not need to work in Perl 4.
Perl source code should follow the conventions for C source code
where applicable.
/*
* Copyright (C) 1996-2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#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. */
#include <isc/lang.h>
/***
*** Types
***/
/* (Type definitions here.) */
/***
*** Functions
***/
ISC_LANG_BEGINDECLS
/* (Function declarations here, with full prototypes.) */
ISC_LANG_ENDDECLS
#endif /* ISC_WHATEVER_H */
C Source
Including Interfaces (.h files)
The first file to be included in a C source file must be config.h.
The config.h file must never be included by any public header file
(that is, any header file that will be installed by "make install").
Try to include only necessary files, not everything under the sun.Statements
There should be at most one statement per line. The comma operator
should not be used to form compound statements.
if (i > 0) {
printf("yes\n"); i = 0; j = 0;
x = 4, y *= 2;
}
Functions
The use of ANSI C function prototypes is required.
To suppress compiler warnings, unused function arguments are declared
using the
static inline void
f(int i) {
/* whatever */
}
int
g(int i, /* other args here */
int last_argument)
{
return (i * i);
}
UNUSED()
macro.REQUIRE()
s, UNUSED()
declarations, and other
code, in this order. These sections are separated by blank lines.Curly Braces
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.if, for
or
while
) has only a single action associated with it, then no
bracing is used around the statement. Exceptions include when the
compiler would complain about an ambiguous else clause, or when extra
bracing improves the readability (a judgement call biased toward not
having the braces).
Bad:
static void
f(int i) {
if (i > 0) {
printf("yes\n");
i = 0;
} else
printf("no\n");
}
void f(int i)
{
if(i<0){i=0;printf("was negative\n");}
if (i > 0)
{
printf("yes\n");
i = 0;
}}
Spaces
malloc(4 * sizeof(long))
.
Return Values
If a function returns a value, it should be cast to (void) if you don't
care what the value is, except for printf
and its variants,
fputc
, fwrite
(when writing text),
fflush
,
memcpy
, memmove
, memset
,
strcpy
, strncpy
, and strcat
.
openlog
and srandom
.
The return value of these should not be used nor cast to (void).
Not so good:
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;
}
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;
}
Integral Types
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.Casting
Casting should be avoided when possible. When it is necessary, there
should be no space between the cast and what is being cast.
(void) malloc(SMBUF);
Clear Success or Failure
A function should report success or failure, and do so accurately. It
should never fail silently. Use of Design by Contract can help here.Testing Bits
Bit testing should be as follows:
Bad:
/* 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)) {
}
/* Test if flag set. */
if (flags & FOO) {
}
/* Test if flag clear. */
if (! (flags & BAR)) {
}
Pointers
Null Pointer
The null pointer value should be referred to with "NULL", not with "0".
Testing to see whether a pointer is NULL should be explicit.
char *c = NULL;
/* ... */
if (c == NULL) {
/* Do something. */
}
Invalidating Pointers
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.
char *text;
/* text is initialized here. */
free(text);
text = NULL;
Testing for Zero or Non-zero
Explicit testing against zero is required for numeric, non-boolean variables.
Bad:
int i = 10;
/* ... */
if (i != 0) {
/* Do something. */
}
int i = 10;
/* ... */
if (i) {
/* Do something. */
}
The Ternary Operator
The ?: operator should mostly be avoided. It is tolerated when
deciding what value to pass as a parameter to a function, such as
frequently happens with printf, and also when a simple (non-compound)
value is being used in assignment or as part of a calculation.
In particular, using the ternary operator to specify a return value is
verboten.
Bad:
printf("%c is%s a number.\n", c, isdigit(c) ? "" " NOT");
l = (l1 < l2) ? l1 : l2;
if (gp.length + (go < 16384 ? 2 : 3) >= name->length) {
...
}
return (success ? ISC_R_SUCESS : ISC_R_FAILURE);
Assignment in Parameters
Variables should not have their values assigned or changed when being
passed as parameters, except perhaps for the increment and decrement
operators.
Ok:
malloc(size = 20);
fputc(c++, stdout);
Namespace
Public Interfaces
All public interfaces to functions, macros, typedefs, and
variables provided by the library, should use names of the form
{library}_{module}_{what}, such as:
however, structures which are typedef'd generally have the name of the
typedef sans the final _t:
isc_buffer_t /* typedef */
dns_name_setbuffer(name, buffer) /* function */
ISC_LIST_HEAD(list) /* macro */
isc_commandline_argument /* variable */
Generally speaking macros are defined with all capital letters, but
this is not universally consistent (eg, numerous isc_buffer_{foo}
macros).
struct dns_rbtnode {
/* ... members ... */
}
Shared Private Interfaces
When a module provides an interface for internal use by other modules
in the library, it should use the same naming convention
described for the public interfaces, except {library} and {module}
are separated by a double-underscore. This indicates that the name is
internal, its API is not as formal as the public API, and thus it
might change without any sort of notice.
Initialization
When an object is allocated from the heap, all fields in the object must be
initialized.Dead Code Pruning
Source which becomes obsolete should be removed, not just disabled with
#if 0 ... #endif.Log messages
Error and warning messages should be logged through the logging
system. Debugging printfs may be used during development, but
must be removed when the debugging is finished. The
UNEXPECTED_ERROR()
macro is obsolete and
should not be used in new code."zone '%s' is lame"
.isc_log_write(... "open: %s: %s", filename,
isc_result_totext(result));
Perl source code
Perl must not be required for building, installing, or using the BIND 9
name server. It may be used for things like test scripts and optional
server add-on components.