The old versions of equal-ops =+, =-, =*, etc. should not be used. The preferred use is +=, -=, *=, etc. All binary operators except . and -> should be separated from their operands by blanks (footnote 24). In addition, keywords that are followed by expressions in parentheses should be separated from the left parenthesis by a blank (footnote 25). Blanks should also appear after commas in argument lists to help separate the arguments visually. On the other hand, macros with arguments and function calls should not have a blank between the name and the left parenthesis. In particular, the C preprocessor requires the left parenthesis to be immediately after the macro name or else the argument list will not be recognized. Unary operators should not be separated from their single operand. Since C has some unexpected precedence rules, all expressions involving mixed operators should be fully parenthesized.
a += c + d;
a = (a + b) / (c * d);
strp->field = str.fl - ((x & MASK) >> DISP);
while (*d++ = *s++)
; /* EMPTY BODY */
Individual projects will no doubt have their own naming conventions. There are some general rules however.
- An initial underscore should not be used for any user-created names (footnote 26). Unix uses it for names that the user should not have to know (like the standard I/O library) (footnote 27).
- Macro names, typedef names, and define names should be all in CAPS.
- Variable names, structure tag names, and function names should be in lower case (footnote 28). Some macros (such as getchar and putchar) are in lower case since they may also exist as functions. Care is needed when interchanging macros and functions since functions pass their parameters by value whereas macros pass their arguments by name substitution (footnote 29).
Numerical constants should not be coded directly (footnote 30). The define feature of the C preprocessor should be used to assign a meaningful name. This will also make it easier to administer large programs since the constant value can be changed uniformly by changing only the define. The enumeration data type is the preferred way to handle situations where a variable takes on only a discrete set of values, since additional type checking is available through lint.
There are some cases where the constants 0 and 1 may appear as themselves instead of as defines. For example if a for loop indexes through an array, then
for (i = 0; i < ARYBOUND; i++)
is reasonable while the code
fptr = fopen(filename, "r");
if (fptr == 0)
error("can't open %sn", filename);
is not. In the last example the defined constant NULL is available as part of the standard I/O library’s header file stdio.h and must be used in place of the 0.