Table of Contents Previous Chapter
All source code consists of printable ASCII characters, separated into lines by standard control characters, such that lines are no longer than 80 characters. The ANSI C string constant concatenation feature is used to break long strings into manageable pieces.
Simple statements are aligned vertically on independent lines. All simple statements, even null statements, should be placed on an independent line.
while (*c++ = getchar())while (*c++ = getchar()); ; int main(int argc, char **argv) { short i; scrOpen(); scrClear(); plotTrk(i, 'X'); scrCurs(scrLines - 1, 0); scrClose(); }
XtSetArgs(args[i], XtNheight, &height); i++; XtSetArgs(args[i], XtNwidth, &width); i++;
One level of standard indentation corresponds to four columns. Indentation may consist of any combination of tabs and spaces.
Braces delimiting the body of a compound statement are aligned vertically with each other and with the statements they enclose. The opening brace is on a separate line, and indented one level from the phrase on the preceding line. Braces used to delimit enumerated type definitions, or to initialize arrays or structures, however, may appear on the same line as their contents when the entire statement fits on a single line.
typedef enum { Red, White, Green, Black, Orange, Blue, Yellow } Colors; long lengths[] = { 22, 44, 3, 25 }; typedef struct { long length; long width; } Size; Size sizes[] = { { 2, 4 }, { 4, 8 }, { 8, 16 }, { 16, 32 }, { 32, 64 }, { 64, 128 }, { 128, 256 } }; typedef struct { char *process_name; char *input_dir; char *output_dir; short priority; unsigned long report_period; unsigned long data_freq; char *formats[3]; int input_fmt; int output_fmt; unsigned long timeout; } ProcConfig; ProcConfig filterProc = { "DAILY_FILTER", "/usr/local/profiler_hourly", "/usr/local/profiler_daily", 10, 3600 * 24, 3600, { "/usr/local/formats/profiler_fmt", "/usr/local/formats/bufr_fmt", NULL }, 0, 1, 1800 };
Control statements adhere to the previous rule when the statement body is a compound statement, but the more general convention for control statements is as follows. The body of a control statement and/or control clause is indented one standard indentation from its associated control phrase. Nested control statements have a corresponding nested indentation.
while (inventory > 0)while (inventory > 0) { { CountOne(); CountOne(); inventory--; inventory--; } } while (inventory > 0) { CountOne(); inventory--; } while (inventory > 0) { CountOne(); inventory-- } while (inventory > 0) { CountOne(); inventory-- } switch (a) { case 0: tooLow(a); switch (base) break; { case 1: case 2: printBinary(value); break; case 2: case 10: printf("value=%d\n", value); break; case 3: case 16: printf("value=0x%x\n", value); break; justRight(a); default: printf("Unknown base.\n"); break; break; } default: tooHigh(a); break; }
Braces delimiting a function definition are indented one standard indentation. The entire body of the function definition is indented. This is consistent with control statement formatting.
/*------------------------------------------------------------------------- ** menuSequence() ** This routine handles a sequence of menu interactions with a user. ** ** Menu *menuPtr; Reference to initial menu to be displayed. ** ** Returns status of user interaction. **-------------------------------------------------------------------------*/ MenuStatus menuSequence(Menu *menuPtr) { int i; MenuStatus status = MENU_NORMAL; char selector = '\0'; /* This function generates a series of menu screens to a user */ while (menuPtr != NULL) { /* Initialize the menu window */ initMenu(menuPtr); /* Generate each menu line */ for (i=0; i<menuPtr->nlines; i++) { selector = computeSelector[i]; addMenuLine(menuPtr->lines[i], selector); } /* Respond to selections until next menu is requested. */ while ((choice = queryUser()) != 0) { if (choice <= menuPtr->maxChoice) status = processChoice(menuPtr, choice) else displayError(choice); } /* Abort further menus if an exit has been requested. */ if (status & MENU_EXIT) break; menuPtr++; } return status; }
void shoot_arrow(void) void shoot_arrow(void) void shoot_arrow(void) { { { int i; int i; int i; ... ... ... return; return; return } } }
The do-while statement always appears with braces. Both do-while statements and typedef statements containing aggregates require a phrase to appear after the closing brace. These trailing phrases always appear on the same line as the closing brace.
/* Drawing characteristics. */ typedef struct { Color color; int width; Pattern pattern; } BrushDef; do { processPage(ipage); ipage += page_inc; } while ((page < last) && (page > 0));
Braces are always used when nesting if-else clauses (except when simply concatenating them using the "else if" technique described below), thereby avoiding possible ambiguity in the association between clauses.
if (a >= 0) { if (a > MaxValue) overflow = TRUE; else a = -1; }
The else if technique shown below is used when chaining if and else clauses. Any number of clauses may be chained. The use of a switch may be more efficient, but has limited means of defining cases.
if (a > 0) a = 1; else if (a < 0) a = -1; else a = 0;
Commas are not used to concatenate expressions within an executable statement, except within control phrases. Commas are also used within parameter lists and aggregate initializations, enumerated type definitions, and variable declarations.
XtSetArgs(args[i], XtNheight, &height); x = y = z = 0.0; typedef enum { APPLE, ORANGE, PEACH, BANANA, PINEAPPLE }; float x, y, z; /* Projectile coordinates */ for (i=0, ptr=buffer; i < MAX; i++, ptr++) ...
XtSetArgs(args[i], XtNheight, &height), i++; XtSetArgs(args[i], XtNheight, &height), i++; x = 0.0, y = 100.0, z = 10.0;
Source files must be viewable, printable, and editable on a variety of platforms. Use of line lengths greater than 80 columns and/or use of control or unprintable characters (excepting tabs and newlines), are not in keeping with this requirement. Although the use of 132 columns is supported by some machines and editors, it requires use of a small font, and often will not print on standard 81/2 x 11 paper in a standard orientation. Source files must also increasingly be transportable across networks and interpretable by telecommunications software.
Proper function modularity and the ability to break statements over multiple lines eliminate the need for excessively long lines. Concatenation of string constants, a feature available on ANSI C compilers, facilitates the breaking of long strings into lines of appropriate length. The backslash character notation is used to represent unprintable or nonASCII characters in terms of multiple ASCII printable characters. This syntax may be used wherever string or character literals are used in the C language.
Statements are placed one per line so that they may be easily located and manipulated as discrete entities. The free-form nature of the C language does not require any association at all between statements or statement clauses and lines. In practice, however, code is cumbersome to maintain unless there is a strict association between a statement or statement clause and a line. The techniques of indentation and placement of statement clauses on distinct lines work together to allow clauses and statements to be readily located and operated upon as modular elements. The pace with which software may be developed and maintained is significantly affected by the degree of standardization adopted in the form and placement of statements. When developing code for individual use, there may be little need for a programmer to deviate from personal preferences. In a team programming or project-oriented environment, however, software is usually designed and implemented as collections of reusable components. Standardization facilitates this reuse. Programmers accustomed to other languages, particularly FORTRAN, may find some of these placement and spacing rules unusual. Most C programmers in a commercial or production development envioronment promote these or similar conventions as good programming practice.
Braces are used in the C language to group simple statements into compound statements. Compound statements are used in conjunction with control statements, often forming the bodies of such statements. The C compiler ignores white space (carriage returns, spaces, etc.), so there is a great deal of flexibility with regard to the placement of braces and the use of indentation to affect code appearance. The three brace placement conventions depicted below are widely used. The first line of each example contains a control phrase. The statements grouped into each compound statement are indented to distinguish them from subsequent statements not associated with the control phrase.
if (notEqual && (first > second)) { temp = dataPtr[first]; dataPtr[first] = dataPtr[second]; dataPtr[second] = temp; } if (notEqual && (first > second)) { temp = dataPtr[first]; dataPtr[first] = dataPtr[second]; dataPtr[second] = temp; }
if (notEqual && (first > second)) { temp = dataPtr[first]; dataPtr[first] = dataPtr[second]; dataPtr[second] = temp; }
The first style shown is that used by the originators of the C language, and is noted for the drawback that opening braces are sometimes lost within large control statements, causing them to be easily missed when code is rearranged or indentations modified. The second style shown was adopted largely to avoid the likelihood of misinterpretation associated with the original style by emphasizing the presence of braces. The third style shown fits the language more naturally than does the second style, for it logically indents the entire compound statement as a unit, just as a single simple statement would be indented. This third style, which has been promoted for many years by Thomas Plum, the Vice-Chairman of the ANSI C standards committee, has been adopted as an integral part of these conventions.
Note that many of the other conventions within this document are adapted to this style of brace placement so as to give the code a consistent appearance. In this sense, conventions are not independent of each other, even though they are defined independently. Although, as mentioned above, other reasonable conventions exist and are widely used, the need for overall consistency in code appearance precludes allowing more than a single style of brace placement. If more than one style were permitted here, then other conventions would logically have to allow a preferred style for each form of brace placement. The effectiveness of these conventions would then be significantly reduced. Having to mentally map one style into another, or having to reformat code fragments when reusing them, can significantly slow development. One can therefore argue that the particular style used is less important than that there be only a single style used. The adopted style has been selected to promote readability.
Indentation is four columns wide, in the form of spaces and/or tabs. The four column indentation is widely used, and nicely allows a one-half indentation of 2 columns to be used for continuation lines. Many editors (particularly those standard in a UNIX environment) provide automatic indentation with a setable tabstop, making indentation easy to implement. Tabstops can be problematic when automatically expanded to 8 characters by printers and source debuggers. If this is a problem, one may either use spaces for indentation, or may expand tabs to spaces with an appropriate utility (expand on UNIX systems).
Most of the convention definitions associated with control phrases provide examples of how these conventions are used. The following examples further illustrate some of these conventions, and indicate the types of problems avoided through their use.
do { processPage(ipage); ... ... ... ... -------page break------- --------continuing on next page-------- ... ... ... ... ... ipage += page_inc; } while ((page < last) && (page > 0));
switch (a) { case 0: tooLow(a); break; case 1: case 2: case 3: justRight(a); break; default: tooHigh(a); break; }
if (a < b) if (a < c) min = a; else min = b;
if (a < b) { if (a < c) min = a; else min = b; }
if (a < b) { if (a < c) min = a; } else min = b;
if (a < 10) digits = 1; else if (a < 100) digits = 2; else if (a < 1000) digits = 3; else if (a < 10000) digits = 4; else { digits = 5; overflow = TRUE; }
if (a < 10) digits = 1; else { if (a < 100) digits = 2; else { if (a < 1000) digits = 3; else { if (a < 10000) digits = 4; else { digits = 5; overflow = TRUE; } } } }