0. The summary
This article is translated from "recommended C Style and coding standards".
Author Information:
L.W Cannon (Bell Labs)
R.A Elliott (Bell Labs)
L.W Kirchhoff (Bell Labs)
J.H Miller (Bell Labs)
J.M Milner (Bell Labs)
R.W Mitze (Bell Labs)
E.P Schan (Bell Labs)
N.O Whittington (Bell Labs)
Henry Spencer (Zoology Computer Systems, University of Toronto)
David Keppel (EECS, UC Berkeley, Cs&e, University of Washington)
Mark Brader (SoftQuad?) Incorporated, Toronto)
This is an updated version of the Indian Hill C Style and coding standards, which was modified by the last three authors mentioned above. This paper introduces a recommended coding standard of C program, which focuses on the coding style rather than functional organization (functional organization).
1. Introduction
This document is modified in a document of a committee established within the At&t Indian Hill Laboratory to establish a common coding standard and recommend it to the Indian Hill community.
This article mainly describes the coding style. A good style can encourage a consistent code layout, improve code portability, and reduce the number of errors.
This article does not focus on functional organizations, or on general topics such as how to use Goto. We tried to integrate the previous C-code-style document into a unified set of standards that would be appropriate for any project using C, and of course some of the content was directed at a particular system. In addition inevitably are these standards still unable to cover all situations. Experience and a wide range of evaluations are important, and when it comes to special situations, you should consult experienced C programmers or see the code of the experienced C programmers (preferably following these rules).
The standards in this article are not required in themselves, but may be used by individual agencies or groups as part of the acceptance process. As a result, other people in your organization are likely to encode in a similar fashion. Ultimately, these standards are designed to improve portability, reduce maintenance, and especially improve the clarity of your code.
There are a number of arbitrary styles that are chosen here. Mixed coding styles are more difficult to maintain than bad coding styles, so when you change existing code, it's best to keep the same style as your existing code, rather than blindly follow the rules in this document.
"Clear is professional, not clear is layman's"-sir Ernest Gowers
2. Organization of documents
A file contains parts that should be separated by several blank lines. Although there is no maximum length limit for source files, more than 1000 rows of files are not easily processed. The editor probably does not have enough temporary space to edit the file, and the compilation process becomes very slow. It is not worthwhile to compare the amount of time it takes to roll back to the front, and we discourage the use of multiple planets that only present very little information. Rows exceeding 79 columns cannot be handled well by all terminals and should be avoided as much as possible. Too long rows cause deep indentation, which is often a symptom of poorly organized code.
2.1 File Naming conventions
The file name consists of a base name, an optional period, and a suffix. The first character of a name should be a letter, and all characters (except a period) should be lowercase letters and numbers. The base name should consist of eight or fewer characters, and the suffix should consist of three or fewer characters (four if you include a period). These rules apply to program files and to the default files that are used and produced by the program (for example, "Rogue.sav").
Some compilers and tools require file names to conform to specific suffix naming conventions. The following are suffix naming requirements:
c The name of the source file must end with. C
The name of the assembly source file must end with. s
We generally follow the following naming conventions:
Relocatable destination file name ends with. o
Header filename ends with. h
A better convention to choose from in a multilanguage environment is to use the language type and. h as the suffix (for example, "foo.c.h" or "foo.ch").
YACC source filename ends with. y
Lex source filename ends with. l
C + + uses compiler-related suffix conventions, including. C,. C,.CC,.C.C and. C. Since most C code is also C + + code, there is no clear solution here.
In addition, we generally agree to use "Makefile" instead of "Makefile" as the control file for make (for those systems that support make) and use "README" as a brief description of the contents or directory tree of the directory.
2.2 Program Files
The following is the recommended order of the various components of a program file:
The first part of the file is an order that describes what the content in the file is. The use of objects in a file (whether they are functions, external data declarations or definitions, or something else) is more useful than a list of object names. This sequence can optionally include author information, revision control information, and reference materials.
Next is all the included header files. If the reason why a header file is contained is not so obvious, we need to explain the reason by adding a comment. In most cases, a system header such as stdio.h should be placed in front of the user's custom header file.
Next comes the defines and typedefs that are used for the file. A general order is to write Chang first, then write function macros, and finally typedefs and enum (enums) definitions.
Next is the global (external) data declarations, usually in the following order: external variables, non-static (non-static) global variables, static global variables. If a set of definitions is used for some specific global data (such as a glyph), then these definitions should be placed after the corresponding data declaration or embedded in the structure declaration, and the definitions are indented to the next level of the first keyword of the declaration to which they are applied (I really don't understand the meaning of the following sentence).
The last is the function, which should be arranged in a meaningful order. Similar functions should be put together. In contrast to depth first (function definitions as much as possible before and after their callers), we should prefer the breadth-first approach (together with functions of similar abstraction levels). There needs to be quite a lot of judgment here. If you define a large number of tool functions that are inherently unrelated, consider arranging them in alphabetical order.
2.3 Header Files
Header files are those files that were included in other files by the C preprocessor before compilation. Some header files, such as stdio.h, are defined at the system level, and all programs that use the standard I/O libraries must contain them. Header files are also used to contain data declarations and definitions, which are more than one program needs. Header files should be organized in a functional way, for example, the declaration of a stand-alone subsystem should be placed in a separate header file. If a set of declarations is highly likely to change when code is ported from one machine to another, these declarations should also be placed in separate header files.
Avoid the name of the private header file as the name of the standard library header file. The following statement:
Copy Code code as follows:
When the expected header file is not found in the current directory, it will contain the math header file in the standard library. If this is really what you expect, please add a comment. Do not use absolute paths when including header files. Use <name> include header files when getting header files from a standard location, or define them relative to the current path. The C compiler's "include-path" option (-L in many systems) is the best way to process extended Private library header files, allowing the organization of the directory structure to be organized without changing the source files.
A header file that declares a function or an external variable should be contained in a file that defines those functions and variables. This allows the compiler to do a type check, and the external declaration will always be consistent with the definition.
Defining a variable in a header file is often a bad idea, often a symptom of poorly dividing code between files. In addition, in a single compilation, such as typedef and initialized data definitions cannot be seen by the compiler two times. In some systems, repeated uninitialized definitions that do not decorate with the extern keyword can also cause problems. When the head file is nested, a duplicate declaration occurs, which causes the compilation to fail.
Header files should not be nested. The order of a header file should describe the practical features of other included header files that it uses. In exceptional cases, it is acceptable to include a common header file in a separate header file when a large number of header files need to be included in several different source files.
A common practice is to add the following code to each header file to prevent the header file from being accidentally included multiple times.
Copy Code code as follows:
#ifndef Example_h
#define Example_h
... * * Body of example.h File/*
#endif/* Example_h * *
We should not be dependent on this mechanism that avoids multiple inclusions, especially if it should not be nested with header files.
2.4 Other documents
Another practice is to write a file called "README" to describe the overall situation of the program and the problem. For example, we often include a list of conditional compilation options used by the program and instructions, as well as a list of machine-independent files.
3. Note
"When code is inconsistent with annotations, both of them are probably wrong"--Norm Schryer
Comments should describe what happened, how it was done, what the parameters mean, what global variables were used and modified, and what constraints or bugs. Avoid annotating code that is clear to itself, because these annotations will quickly become obsolete. Comments that are inconsistent with code can have a negative impact. Short notes should be about what to do, such as "calculating meaningful values," rather than "how to do", such as "sum of values divided by n". C is not a compilation; Adding a comment to the area of the first 3-10 lines, explaining what the code is all about, is often more useful than adding a note to each line.
Comments should be "defended" for unpleasant code. The defense should be this: if you use normal code, something bad is going to happen. But just letting the code run faster is not enough to rationalize the hack code, but rather the performance data that is unacceptable when you don't use hack code. Comments should explain the unacceptable behavior and tell you why using hack code is a good way to solve the problem.
Comments that describe data structures, algorithms, and so on should be in the form of block annotations. Block comments start with/* Occupy 1-2 columns, * placed in the second column before each line comment, and the block comment ends with a 2-3 column. Another candidate is to use * to occupy 1-2 columns in front of each line of comment text, and a block comment to occupy 1-2 columns.
Copy Code code as follows:
/*
* Here's a block comment.
* The comment text should is tabbed or spaced over uniformly.
* The opening Slash-star and closing Star-slash are alone on a line.
*/
/*
* * Alternate format for block comments
*/
Attention
Copy Code code as follows:
All comments in the file will be matched. Particularly long block notes, such as persistent discussions or copyright notices, are often started with a/* that occupies 1-2 columns, and there is no * before each line of comment text, and ends with a 1-2 column. Within a function it is appropriate to use a block annotation, which should have the same indentation as the code it describes. A stand-alone single-line comment should also be consistent with the code that it describes.
Copy Code code as follows:
if (argc > 1) {
/* Get input file from command line. */
if (Freopen (argv[1], "R", stdin) = = NULL) {
Perror (argv[1]);
}
}
A specially short annotation can be placed on the same line as the code it describes and separated from the code statement by the TAB key. If you have more than one short comment for a piece of code, these annotations should have the same indentation.
Copy Code code as follows:
if (a = = EXCEPTION) {
b = TRUE; /* Special Case * *
} else {
b = IsPrime (a); * Works is for odd a * *
}
4. Statement
Global declarations should start with the first column. The extern keyword should be placed before all external data declarations. If an external variable is an array of the size determined at the time of the definition, the array bounds must be indicated at the extern declaration unless the size of the array is encoded with the array itself (for example, a read-only character array that always ends with a 0). Repeating the size of an array is especially useful for people who use code written by others.
The pointer modifier * should be associated with the variable name, not with the type.
Copy Code code as follows:
Replace
Copy Code code as follows:
The latter is wrong, because actually T and U are not declared as pointers as expected.
Unrelated declarations, even those of the same type, should occupy one row independently. We should comment on the role of the declaring object, but when the constant name itself is sufficient to describe the role, the list of constants defined using #define does not require a comment. Often, multiple-row variable names, values, and annotations use the same indentation, so that they are on a list of lines. Try to use tab characters instead of spaces. When you declare a struct and a consortium, each element should occupy a single line and be accompanied by a comment. {should be placed on the same line as the tag name of the structure body,} should be placed in the first column at the end of the declaration.
Copy Code code as follows:
struct Boat {
int wllength; /* Water line length in meters * *
int type; * * below *
Long Sailarea; /* Sail area in square mm * *
};
/* Defines for Boat.type * *
#define KETCH (1)
#define YAWL (2)
#define SLOOP (3)
#define SQRIG (4)
#define MOTOR (5)
These defines are sometimes placed after the struct body type declaration and are indented to the next level of the member member of the struct by using enough tab. It would be better to use an enum if these actual values were less important.
Copy Code code as follows:
Enum BT {ketch=1, yawl, sloop, Sqrig, MOTOR};
struct Boat {
int wllength; /* Water line length in meters * *
Enum BT type; /* What kind of boat * *
Long Sailarea; /* Sail area in square mm * *
};
Any variable that is important to the initial value should be explicitly initialized, or at least a comment should be added stating that the default initializer for C is 0. Null initialization ' {} ' should never be used. Structure initialization should be fully enclosed in curly braces. Constants that are used to initialize long integers should use an explicit length. Using uppercase letters, such as 2l, looks more like 21, the number 21.
Copy Code code as follows:
int x = 1;
Char *msg = "message";
struct boat winner[] = {
{yawl, 6000000L},
{A, MOTOR, 0L},
{0},
};
If a file is not a stand-alone program, but a part of a project as a whole, then we should maximize the use of the static keyword so that functions and variables are local to a single file. We allow variables to be accessed by other files only when there is a special case with clear requirements that cannot be implemented in other ways. In this case, you should use annotations to explicitly inform you of the use of variables in other files, and you should specify the names of other files. If your debugger obscures the static objects that you need to view during the debugging phase, you can declare these variables static and decide whether to #define static as needed.
The most important types should be typedef, even if they are just integers, because independent names make the program more readable (if there are only a few integer typedef). The struct body should be typedef when declared. Keep the name of the structure symbol the same as the name after the typedef.
Copy Code code as follows:
typedef struct SPLODGE_T {
int sp_count;
Char *sp_name, *sp_alias;
} splodge_t;
Always declare the return type of the function. If the function prototype is available, use it. A common mistake is to ignore external mathematical function declarations that return a double. In that case, the compiler assumes that the return value of these functions is an integer and converts the bit-bit-by-conscientious attention to a floating-point number (meaningless).
"One of the views of the C language is that programmers are always right"-michael Decorte
5. Function declaration
Each function should precede a block of comments outlining what the function does and, if not very clearly, how to use the function. Important design decision discussions and side-effects statements are also appropriate for annotations. Avoid providing information that the code itself can provide clearly.
The return type of a function should occupy a single row, optionally indented one level. Do not use the default return type int; If the function does not return a value, the return type is declared void. If the return value requires a large section of detailed description, it can be described in a comment before the function, otherwise you can comment on the return type in the same row. The function name (and the form argument list) should be placed on a single line, starting with the first column. The purpose (return value) parameter is generally placed at the first parameter position (starting from the left). All formal parameter declarations, local declarations, and code in the body of the function should be indented one level. The opening parenthesis of the function body should be on a single line, placed at the beginning of the first column.
Each parameter should be declared (do not use the default type int). Usually the role of each variable in a function should be described clearly, we can describe it in the function annotation, or if each declaration is a single line, we can put the comment on the same line. Such simple variables as the loop counter "I", the string pointer "s" and the integer type "C" used to identify the character do not need to be commented on. If a group of functions have a similar parameter or local variable, it is useful to use the same name in all functions to identify the variable (instead of using a name to identify a variable of different use in the correlation function). Similar parameters in different functions should also be placed in the same position in each argument list.
Comments for parameters and local variables should be uniformly indented to form a column. A local variable declaration applies a blank line separated from the function statement.
Be careful when you use or declare functions that have variable length parameters. Currently there is no really portable way to handle variable-length parameters in C. It is best to design an interface that uses a fixed number of parameters. If you must use variable-length parameters, use macros in the standard library to declare functions that have variable-length arguments.
If the function uses an external variable (or function) that is not declared globally in the file, we should declare the variables separately using the extern keyword inside the function body.
Avoid local declarations overwriting high-level declarations. In particular, local variables should not be declared in nested blocks of code. While this is legal in C, when the-H option is used, the potential conflict is likely enough to make the lint tool complain.
Current 1/3 page
123 Next read the full text