Understanding the C language-the path to Promotion from a side dish to a great God (15)-conclusion: C programming style
Someone said: "The program source code is actually read by people, but the machine can compile it ". Programming beginners often have the idea that as long as my program passes compilation and runs without any problems, everything will be fine. As for the nonstandard coding rules, it is completely irrelevant. If it is in the learning stage, for example, in order to complete the C language class assignments in the school, there is no special need to worry about code specifications, because these codes will not basically enter practical engineering, it will not be read by many people.
However, if it is applied to engineering, such as open-source engineering on software/Internet Enterprise Technical R & D departments, Github, and other platforms, the standardization of programming will become extremely important. Because in these cases, the code you write will be read by many people and may become the basis for subsequent development by many people. At this point, the poor code style will seriously reduce the efficiency of other developers. Therefore, we recommend developing a good programming habit from the very beginning to maintain a reasonable code style, which will be of great benefit to future work.
The content of the C language programming style is quite large. Here we only select a part of the content that is relatively common and important as a reference, which is mainly divided into five parts, includes typographical, comments, naming, variables/structures, and functions.
1. Layout
Program layout makes the code structure clearer and easier to understand the logical relationship of context.
(1) The program block should adopt the indent style according to the context relationship, and the indent length should be subject to specific standards;
(2) Empty lines must be added between independent program blocks and variables. For example:
int fun(){ int nVal1 = 0, nVal2 = 5, nSum; { nSum = nVal1 + nVal2; } printf("Sum is %d\n", nSum);}
(3) A statement occupies one row. Two statements cannot be written in one row;
(4) for code with judgment and loops, such as if/for/do/while/case/swith/default, the portion occupies one row exclusively and no matter how many statements are executed, all must use braces {};
(5) The braces {} of the wrapped code block must start with another line. Do not follow the end of the previous line of code. The braces must also comply with the code indent rules;
2. Notes
Annotations do not affect the running of programs, but are still an important part of the code. A complete code annotation is of great significance to quickly understand the functions of the Code. On the contrary, if the code logic is complex and there is no annotation, or the annotation is incomplete or unscientific, it is difficult for others to understand what the code is. Note that programs that cannot be understood by others are always spam code even if they run well.
Note that annotations should be concise and effective to help you better understand the code. Therefore, do not add meaningless or error messages when adding annotations. Generally, we think that a set of code is divided into four levels based on advantages and disadvantages:
Level 1: code with high readability can be achieved through excellent code styles, identifiers, and context relationships of Codes Without comments;
Level 2: code naming and organization specifications and styles are slightly inadequate, but there are well-developed annotations;
Level 3: The Code style and comments are not perfect, but the well-organized documents make up for this defect to some extent;
Level 4: Code style, comments, and documentation are insufficient, which is a type of spam code that is hard to understand by others.
Comment on the function header:
Add comments to the function header to describe the functions, parameters, return values, and other information of the function. The following annotations do not have to be limited to these annotations, but we recommend that you keep most of the information:
/*************************************** * ********* Function: // Function Name Description: // function, performance, and other descriptions CILS: // list of functions Called By this function Called By: // function list for calling this function Input: // input parameter description, including the operation and use of each parameter, value description, and relationship between parameters. Output: // description of the Output parameters. Return: // description of the function Return value Others: // other instructions ************************************ *************/
Comments in the Code:
The statement comment should be on the top or right of the commented statement. If it is above, do not insert spaces between the code and comments unless necessary.
For constants, variables, and data structures with physical meanings, unless the name itself is fully annotated, it must be annotated during declaration.
Global variables should be annotated in detail, including their functions, value ranges, used functions, and precautions for access.
The comment is separated from the code above by a line of space.
Comments should be added to the selection and loop statements to illustrate the meaning of the branches and loop bodies.
Add a comment to the right of the braces at the end of the block to indicate the starting position of the matched block.
Run the following code:
If (...) {program code while (index <MAX_INDEX) {program code}/* end of while (index <MAX_INDEX) * /// specify the end of the while statement}/* end of if (...) * /// specify which if statement ends
3. identifier name
Identifier naming is an important part of the code style, and even directly determines the readability of the Code. The most common identifiers are constant names, variable/struct names, function names, macro definitions, and tag names. Different requirements are generally applied to different types of identifiers, but some basic requirements are the same: the names of identifiers must be clear and have clear meanings, so use abbreviations as few as possible; it is strictly prohibited to use meaningless words or abbreviations such as a, B, I, m, n, func1, and fun for naming;
(1) constant, variable, and function naming:
For variable names and function names, there are usually two commonly used naming methods: hump naming and underline naming, the fundamental difference between the two methods is how to separate the logical breakpoints in the identifier naming.
Camper name: separated by uppercase/lowercase letters, for example, int imgWidth = 0; char * studentName = "Jerry ";
Underline naming: separated by underscores, for example, double earth_moon_distance;
You can use different naming methods for function names and variable names. However, you must note that the selected naming rules will remain unchanged from start to end. Generally, my personal habit is that the variable name and struct name start with lower case, and the struct name starts with upper case. The function name uses the underline naming method, and the public API starts with an uppercase letter, private functions start with lowercase and are declared as static.
In addition, for constants, struct member variables, and global variables, you can refer to the Hungarian naming rules and add the prefixes c _, m _, and g _ before the variable names _.
(2) macro definition name
All macro-defined names are named in uppercase, and logical breakpoints are separated by underscores (_). For example:
# Define MAX_ARRAY_LENGTH 256
For the macro definition of header file protection, it is named after the header file name. All vertices before the logical breakpoint and extension are replaced by underscores, and an underline is added to the first place, as shown in figure
//ImageProcessing.h#ifndef _IMAGE_PROCESSING_H_#define _IMAGE_PROCESSING_H_/*code*/#endif
(3) Tag Name
Generally, the tag name is used together with the goto statement. Since goto is a relatively unpopular statement, labels are not very common. If it is used, lowercase letters are used and _ label is added to the end, for example:
void test(){ /*code*/ goto end_label; /*code*/end_label: /*code*/ }
4. usage specifications of variables and structures
The use of variables and structures is the most frequent action in programming. If you can correctly regulate the use of variables, it will greatly improve the overall programming style.
(1) initialize the variable immediately after it is defined. Generally, after a numeric variable is set, it can be immediately initialized to 0, a negative number, or other meaningless values. After the pointer variable is defined, it is initialized to NULL immediately. In this way, when you use variables later, you can easily determine whether the variables have been correctly processed to prevent accidental use of uninitialized values.
(2) Unless necessary, minimize the use of global variables and exercise caution when using global variables across files. Global variables are an important factor in code coupling. Generally, the more global variables are used, the more difficult the code is to maintain.
(3) For quantities that should not be changed at all, they are all defined as constants to prevent them from being mistakenly modified.
(4) the more specific the function of defining a struct, the better. A structure that implements multiple functions should not be defined. Another manifestation is that you should not define a structure with a large scale. This will not only waste system resources while running, but also be hard to understand logically.
(5) Unless necessary, reduce the forced conversion between variable types as much as possible. Forced conversion actually requires additional computer operations. Excessive forced conversion is also a waste of system resources.
(6) When defining a struct, pay attention to optimizing the sequence between members and minimize the storage space waste caused by byte alignment.
5. Function usage specification for functions that may encounter execution errors (such as file opening failure), all return error codes through the return value, and the error codes are pre-defined with macros. Unless specifically designed to output random information functions, all functions should be predictable, that is, the same input always produces the same output. A function can only complete one small function to avoid a super-long function that completes a large number of unrelated functions. Strictly differentiate input and output parameters. All parameters that should not be changed in the function body are declared as const type. Before the function starts processing, check the validity of the input parameters and other external applications. Avoid using too long parameter tables. You can encapsulate relevant parameters into a struct and use this struct as the parameter.