logo_kerberos.gif

Difference between revisions of "Coding style/Formatting"

From K5Wiki
Jump to: navigation, search
m (Coding style/C/Formatting moved to Coding style/Formatting: delete one level of hierarchy)
(expand a few sections)
Line 2: Line 2:
   
 
== Maximum width 79 columns ==
 
== Maximum width 79 columns ==
  +
  +
Source code lines should not exceed 79 columns in width.
   
 
=== Current conformance ===
 
=== Current conformance ===
Line 13: Line 15:
 
== Four-column basic indentation offset ==
 
== Four-column basic indentation offset ==
   
Every level of block nesting should be indented by an additional four columns. [needs more detail]
+
Every level of block nesting should be indented by an additional four columns. Labels, including "<code>switch</code>" labels, should be at one less level of indentation than their surrounding code:
  +
  +
<pre>
  +
void
  +
foo(int x)
  +
{
  +
switch (x) {
  +
case 0:
  +
bar();
  +
break;
  +
case 1:
  +
quux();
  +
break;
  +
default:
  +
break;
  +
}
  +
}
  +
</pre>
  +
  +
[needs more detail]
   
 
=== Current conformance ===
 
=== Current conformance ===
Line 34: Line 36:
 
== No tab characters ==
 
== No tab characters ==
   
This guideline will probably be one of the more difficult ones to adopt in a non-disruptive manner.
+
No tab characters should appear in source files. This guideline will probably be one of the more difficult ones to adopt in a non-disruptive manner.
   
 
=== Current conformance ===
 
=== Current conformance ===
   
Existing code does not conform. Much of the existing code was written in Emacs, which defaults to using sequential tab characters at the beginning of stretch of horizontal whitespace longer than one column.
+
Existing code does not conform. Much of the existing code was written in Emacs, which defaults to using sequential tab characters at the beginning of stretches of horizontal whitespace longer than one column.
   
 
=== Rationale ===
 
=== Rationale ===
   
Tab stop locations are not consistent across different editors and platforms, and can make code harder to read on a platform other than the one on which it was written.
+
Tab stop locations are not consistent across different editors and platforms, and can make code harder to read on a platform other than the one on which it was written. Tab characters also make diffs harder to read.
   
 
== No trailing whitespace ==
 
== No trailing whitespace ==
  +
  +
There should be no whitespace at the end of a line. Blank lines should not contain any horizontal whitespace.
   
 
=== Current conformance ===
 
=== Current conformance ===
   
Existing code is highly variable in this area. Particularly problematic are boilerplate, such as copyright notices, which contain trailing whitespace.
+
Existing code is highly variable in this area. Particularly problematic are boilerplate, such as copyright notices, which contain trailing whitespace. Blank lines in code sometimes contain indentation whitespace.
   
 
=== Rationale ===
 
=== Rationale ===
Line 62: Line 66:
 
=== Rationale ===
 
=== Rationale ===
   
== Spacing around delimiters ==
+
== Spacing ==
  +
  +
One space goes after keywords ("<code>if</code>", "<code>for</code>", "<code>while</code>", "<code>for</code>", "<code>do</code>", "<code>switch</code>", and "<code>return</code>"). Do not put a space after "<code>sizeof</code>", but do parenthesize its argument. Do not put a space between a function name and the opening parenthesis of its argument list. Do not put a space after a typecast. Do not put a space between a keyword and its immediately-following semicolon.
  +
  +
<pre>
  +
if (x) {
  +
foo(x);
  +
}
  +
while (y) {
  +
baz(&amp;y);
  +
if (quux())
  +
return;
  +
}
  +
</pre>
  +
  +
Put spaces around binary operators, but not around unary or postfix operators. The structure member operators "<code>.</code>" and "<code>-&gt;</code>" count as postfix operators, not binary operators.
  +
  +
<pre>
  +
x = --a + b / c - d++;
  +
y = p->z.v[x];
  +
</pre>
  +
  +
Omitting spaces around some binary operators may be justified when it improves readability:
  +
  +
<pre>
  +
s[len+1] = '\0';
  +
</pre>
  +
  +
Put spaces around the "<code>?</code>" and "<code>:</code>" characters in a conditional expression:
  +
  +
<pre>
  +
x = y ? f() : g();
  +
</pre>
   
 
=== Current conformance ===
 
=== Current conformance ===
  +
  +
Spacing around binary operators is mostly consistent. Existing code is not consistent about putting the opening parenthesis of a function call immediately after the function name.
   
 
=== Rationale ===
 
=== Rationale ===
  +
  +
Extra spacing around keywords helps to distinguish them from functions. Spacing around binary operators improves readability.
  +
  +
== Function definitions ==
  +
  +
Function names in function definitions should begin at the leftmost column. The type name of a function in a function definition should go on the line preceding the function name. The opening brace of a function definition should also go in the leftmost column. Use ANSI-style function definitions, not the K&amp;R style; the K&amp;R style is obsolescent.
  +
  +
<pre>
  +
char *
  +
foo(int a)
  +
{
  +
/* ... */
  +
}
  +
</pre>
  +
  +
=== Current conformance ===
  +
  +
Existing code is variable.
  +
  +
=== Rationale ===
  +
  +
Placing function names in the leftmost column helps some tools, such as ctags or Emacs.
  +
  +
== Flow control statements ==
  +
  +
Braces opening substatements, such as those following "<code>if</code>", "<code>else</code>", "<code>while</code>", "<code>for</code>", "<code>do</code>", and "<code>switch</code>" should be on the same line as the keyword or expression associated with that substatement. There should be one space before the opening brace. This is sometimes called "hanging" braces. The closing brace of the substatement should be the first non-whitespace character on its line, and be placed at the same indentation level as the keyword for that substatement.
  +
  +
<pre>
  +
if (x) {
  +
foo(x);
  +
}
  +
</pre>
  +
  +
The "<code>while</code>" keyword in a do-while construct should sit on the same line as the closing brace of the substatement following "<code>do</code>":
  +
  +
<pre>
  +
do {
  +
baz();
  +
} while (x);
  +
</pre>
  +
  +
An "<code>if</code>" substatement immediately following an "<code>else</code>" keyword should be on the same line as the "<code>else</code>":
  +
  +
<pre>
  +
if (x) {
  +
foo();
  +
} else if (y) {
  +
bar();
  +
}
  +
</pre>
  +
  +
Do not parenthesize the expression in a "<code>return</code>" statement.
  +
  +
=== Current conformance ===
  +
  +
Existing code mostly conforms. Some Sun-derived code parenthesizes the expressions of "<code>return</code>" statements.
  +
  +
=== Rationale ===
  +
  +
This style is mostly for consistency with the BSD coding style. The GNU brace style consumes a larger amount of vertical space. The "brace-else-if-brace" style also prevents "stairstepping" within a long series of conditional statements.

Revision as of 13:49, 14 April 2008

The following coding style considerations apply to the most mechanical aspects of C source code style.

Maximum width 79 columns

Source code lines should not exceed 79 columns in width.

Current conformance

Existing code mostly conforms to this guideline.

Rationale

A width of 79 columns fits on most terminals, and is most suitable for printing with a decent column width. Long lines resulting from deeply indented code are often a symptom of design flaws.

Four-column basic indentation offset

Every level of block nesting should be indented by an additional four columns. Labels, including "switch" labels, should be at one less level of indentation than their surrounding code:

void
foo(int x)
{
    switch (x) {
    case 0:
        bar();
        break;
    case 1:
        quux();
        break;
    default:
        break;
    }
}

[needs more detail]

Current conformance

Existing code varies in conformance. Much of the core library code (src/lib/krb5, etc.) conforms, but other subsystems chose different indentation offsets. Exceptions include:

  • Code of BSD-related origin -- typically eight columns
    • src/plugins/kdb/db2/libdb2
    • src/lib/rpc
    • Parts of src/lib/gssapi/mechglue
  • Code derived from OpenVision -- various
    • Parts of src/lib/gssapi/krb5
    • src/lib/kadm5
    • src/kadmin

Rationale

Combined with the 79-column width limit, this somewhat limits the level of nesting. This indentation offset allows for visual identification of indentation levels while avoiding long-line problems resulting from using an eight-column indentation offset with some of the long identifier names we use.

No tab characters

No tab characters should appear in source files. This guideline will probably be one of the more difficult ones to adopt in a non-disruptive manner.

Current conformance

Existing code does not conform. Much of the existing code was written in Emacs, which defaults to using sequential tab characters at the beginning of stretches of horizontal whitespace longer than one column.

Rationale

Tab stop locations are not consistent across different editors and platforms, and can make code harder to read on a platform other than the one on which it was written. Tab characters also make diffs harder to read.

No trailing whitespace

There should be no whitespace at the end of a line. Blank lines should not contain any horizontal whitespace.

Current conformance

Existing code is highly variable in this area. Particularly problematic are boilerplate, such as copyright notices, which contain trailing whitespace. Blank lines in code sometimes contain indentation whitespace.

Rationale

Trailing whitespace is difficult to see in many editors. It can also create problems when generating patch files.

Comment formatting

BSD-style block comments. No C99 double-slash comments. Something about Doxygen.

Current conformance

Rationale

Spacing

One space goes after keywords ("if", "for", "while", "for", "do", "switch", and "return"). Do not put a space after "sizeof", but do parenthesize its argument. Do not put a space between a function name and the opening parenthesis of its argument list. Do not put a space after a typecast. Do not put a space between a keyword and its immediately-following semicolon.

if (x) {
    foo(x);
}
while (y) {
    baz(&y);
    if (quux())
        return;
}

Put spaces around binary operators, but not around unary or postfix operators. The structure member operators "." and "->" count as postfix operators, not binary operators.

x = --a + b / c - d++;
y = p->z.v[x];

Omitting spaces around some binary operators may be justified when it improves readability:

s[len+1] = '\0';

Put spaces around the "?" and ":" characters in a conditional expression:

x = y ? f() : g();

Current conformance

Spacing around binary operators is mostly consistent. Existing code is not consistent about putting the opening parenthesis of a function call immediately after the function name.

Rationale

Extra spacing around keywords helps to distinguish them from functions. Spacing around binary operators improves readability.

Function definitions

Function names in function definitions should begin at the leftmost column. The type name of a function in a function definition should go on the line preceding the function name. The opening brace of a function definition should also go in the leftmost column. Use ANSI-style function definitions, not the K&R style; the K&R style is obsolescent.

char *
foo(int a)
{
    /* ... */
}

Current conformance

Existing code is variable.

Rationale

Placing function names in the leftmost column helps some tools, such as ctags or Emacs.

Flow control statements

Braces opening substatements, such as those following "if", "else", "while", "for", "do", and "switch" should be on the same line as the keyword or expression associated with that substatement. There should be one space before the opening brace. This is sometimes called "hanging" braces. The closing brace of the substatement should be the first non-whitespace character on its line, and be placed at the same indentation level as the keyword for that substatement.

if (x) {
    foo(x);
}

The "while" keyword in a do-while construct should sit on the same line as the closing brace of the substatement following "do":

do {
    baz();
} while (x);

An "if" substatement immediately following an "else" keyword should be on the same line as the "else":

if (x) {
    foo();
} else if (y) {
    bar();
}

Do not parenthesize the expression in a "return" statement.

Current conformance

Existing code mostly conforms. Some Sun-derived code parenthesizes the expressions of "return" statements.

Rationale

This style is mostly for consistency with the BSD coding style. The GNU brace style consumes a larger amount of vertical space. The "brace-else-if-brace" style also prevents "stairstepping" within a long series of conditional statements.