• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# C Coding Style Guide
2
3## <a name="c0-1"></a>Purpose
4
5Rules are not perfect. They might disable useful features in specific situations and therefore affect code implementation. However, the purpose of developing rules is to get more benefits for most programmers. If a rule cannot be followed in your team operation, we can improve the rule together. Before referring to this coding style guide, you are expected to have the following basic capabilities of the C programming language:
6
71. Understand the ISO standard of C.
82. Be familiar with the basic features of C.
93. Understand the standard library of C.
10
11## <a name="c0-2"></a>General Principles
12
13Code must meet the requirements for **readability**, **maintainability**, **security**, **reliability**, **testability**, **efficiency**, and **portability** while ensuring functionality correctness.
14
15## <a name="c0-3"></a>Conventions
16
17**Rule**: Conventions that must be followed during programming.
18**Rec**: Conventions that must be considered during programming.
19
20It is necessary to understand the reason for these conventions and try to comply with them, no matter if they are rules or recommendations.
21
22## <a name="c0-4"></a>Exceptions
23
24The only acceptable exceptions are those that do not violate the general principles and provide appropriate reasons for their existence.
25Try to avoid exceptions because they affect the code consistency. Exceptions to 'Rules' should be very rare.
26
27The style consistency principle is preferred in the following case:
28**When you modify open-source or third-party code, comply with their respective code specifications.**
29
30# <a name="c1"></a>1 Naming
31
32Names include file, function, variable, type, and macro names.
33
34Naming is considered the most difficult and important thing in software development.
35The name of an identifier must be clear, well defined, easy to understand, and accounting for reading habits.
36
37The unified naming style is the most direct expression of the consistency principle.
38
39## <a name="c1-1"></a>General Conventions
40
41**CamelCase**
42CamelCase is the practice of writing compound words or phrases so that each word or abbreviation in the phrase begins with a capital letter, and with no intervening spaces or punctuation.
43There are two conventions: **UpperCamelCase and lowerCamelCase**.
44
45**Unix\_like**
46Unix\_like is also known as the snake style. In the Unix\_like style, words contain only lowercase letters and are separated by underscores (\_).
47Example: 'test_result'
48
49### <a name="r1-1"></a>Rule 1.1 Name identifiers in the CamelCase style.
50
51| Type| Naming Style
52|----------|----------
53| Function, struct, enum, union| UpperCamelCase
54| Variable, function parameter, macro parameter, struct body, union member| lowerCamelCase
55| Macro, constant, enumerated value, goto tag| All capitalized, separated by underscores (\_)
56
57Note:
58**Constant** in the above table refers to the variable that is of the basic data type, enum type, and string type and modified by **const** under the global scope, excluding arrays, structs, and unions.
59**Variable** indicates the variables excluding those defined in **Constant**. These variables use the lowerCamelCase style.
60Unix\_like can be used for Linux or Unix friendly code.
61For code that is using the Unix\_like style, you can continue using this style.
62The same naming style must be used for the same function, struct, or union.
63
64### <a name="a1-1"></a>Rec 1.1 Use more accurate names for identifiers with a large scope.
65
66Different from C++, C does not have namespace or class.Therefore, the names of identifiers in the global scope must not conflict with each other.
67Names of global functions, global variables, macros, types, and enums must be accurately described and unique in the global scope.
68
69Example:
70
71```c
72int GetCount(void);                 // Bad: inaccurate description
73int GetActiveConnectCount(void);    // Good
74```
75
76For purposes of accurate naming, a module prefix can be added if necessary.
77The module prefix and the naming body can be connected by following the CamelCase style.
78Example:
79
80```c
81int PrefixFuncName(void);   // OK: CamelCase, a prefix in the content, but not in the format
82
83enum XxxMyEnum {            // OK
84    ...
85};
86```
87
88## <a name="c1-2"></a>File Naming
89
90### <a name="a1-2"></a>Rec 1.2 Use lowercase file names.
91
92Only lowercase letters, numbers, and underscores (\_) are allowed in file names.
93File names should be as short, accurate, and unambiguous as possible.
94The reason for using lowercase file names is that different systems process file names in different ways. (For example, file names in MS-DOS and Windows are not case sensitive, but those in Unix/Linux and macOS are case sensitive by default).
95
96Good example:
97`dhcp_user_log.c`
98
99Bad examples:
100`dhcp_user-log.c`: It is not recommended that you separate words with the hyphen (-).
101`dhcpuserlog.c`: The words are not separated, causing poor readability.
102
103## <a name="c1-3"></a>Function Naming
104
105Functions are named in the UpperCamelCase style.
106
107### <a name="a1-3"></a>Rec 1.3 Name functions to comply with reading habits.
108
109The "verb + object" structure can be used for action related function names. Example:
110
111```c
112AddTableEntry() // OK
113DeleteUser()    // OK
114GetUserInfo()   // OK
115```
116
117An adjective or a prefix "is" can be used in a function returning a Boolean value. Example:
118
119```c
120DataReady()     // OK
121IsRunning()     // OK
122JobDone()       // OK
123```
124
125Data or Getter function:
126
127```c
128TotalCount()    // OK
129GetTotalCount() // OK
130```
131
132## <a name="c1-4"></a>Variable Naming
133
134Variables are named in the lowerCamelCase style. This includes global variables, local variables, parameters in the function declaration or definition as well as parameters in function-like macro.
135
136### <a name="r1-2"></a>Rule 1.2 Add the 'g_' prefix to global variables, but not to static variables in a function.
137
138Global variables should be used as little as possible, and special attention should be paid to their use. This prefix highlights global variables so that developers can be more careful when handling them.
139Global static variables and global variables are named in the same way. Static variables in functions and common local variables are named in the same way.
140
141```c
142int g_activeConnectCount;
143
144void Func(void)
145{
146    static int pktCount = 0;
147    ...
148}
149```
150
151Notes: Constants are also global variables in essence. However, if constants are named using uppercase letters separated by underscores (\_), the current rule does not apply.
152
153### <a name="a1-4"></a>Rec 1.4 Keep local variables short and to the point.
154
155The name of a local variable should be short on the premise that meanings can be expressed through context.
156
157Example:
158
159```c
160int Func(...)
161{
162    enum PowerBoardStatus powerBoardStatusOfSlot; // Not good: Long redundant local variable
163    powerBoardStatusOfSlot = GetPowerBoardStatus(slot);
164    if (powerBoardStatusOfSlot == POWER_OFF) {
165        ...
166    }
167    ...
168}
169```
170
171Better writing style:
172
173```c
174int Func(...)
175{
176    enum PowerBoardStatus status;   // Good: The status can be clearly expressed in context.
177    status = GetPowerBoardStatus(slot);
178    if (status == POWER_OFF) {
179        ...
180    }
181    ...
182}
183```
184
185Similarly, "tmp" can be used to address any type of temporary variable.
186A short variable name should be used with caution, but sometimes a single-character variable is allowed, for example, a counter variable in a loop statement.
187
188```c
189int i;
190...
191for (i = 0; i < COUNTER_RANGE; i++) {
192    ...
193}
194```
195
196Or, variables in simple math functions:
197
198```c
199int Mul(int a, int b)
200{
201	return a * b;
202}
203```
204
205## <a name="c1-5"></a>Type Naming
206
207Types are named in the UpperCamelCase style.
208The type can be a struct, a union, or an enum.
209
210Example:
211
212```c
213struct MsgHead {
214    enum MsgType type;
215    int msgLen;
216    char *msgBuf;
217};
218
219union Packet {
220    struct SendPacket send;
221    struct RecvPacket recv;
222};
223
224enum BaseColor {
225    RED,    // Note: The enum is in the UpperCamelCase style whereas the enumerated values adopt the macro naming style.
226    GREEN,
227    BLUE
228};
229
230typedef int (*NodeCmpFunc)(struct Node *a, struct Node *b);
231```
232
233When you use `typedef` to set an alias for a struct, a union, or an enum, try to use the anonymous type.
234If you need self-nesting pointers, you can add a 'tag' prefix or an underscore suffix.
235
236```c
237typedef struct {    // Good: The anonymous struct is used because self-nesting is not required.
238    int a;
239    int b;
240} MyType;           // The struct alias uses the UpperCamelCase style.
241```
242```c
243typedef struct tagNode {    // Good: Add the 'tag' prefix or use 'Node_'.
244    struct tagNode *prev;
245    struct tagNode *next;
246} Node;             // UpperCamelCase.
247```
248
249## <a name="c1-6"></a>Macro, Constant, and Enum Naming
250
251Use uppercase letters separated by underscores (\_) for macro names and enumerated values.
252You are advised to use uppercase letters separated with underscores (\_) for constant names. Global const variables can be named with the same style of global variables.
253The constants here are defined as global const variables of the basic data type, enum type, or string type.
254
255Use uppercase letters separated by underscores (\_) for function-like macros.
256Exceptions:
2571. Functions that use macros to implement generic functions, for example, macros that implement functions such as list and map, can be named in the same way as functions, using the UpperCamelCase style.
2582. A function-like macro that is used to replace a function in the earlier version can be named in the same way as functions, using the UpperCamelCase style.
2593. Macros for printing logs can be named in the same way as functions, using the UpperCamelCase style.
260Note: Function-like macros named in the UpperCamelCase style must be marked as macros in the API description.
261
262Macro example:
263
264```c
265#define PI 3.14
266#define MAX(a, b)   (((a) < (b)) ? (b) : (a))
267```
268
269```c
270#ifdef SOME_DEFINE
271void Bar(int);
272#define Foo(a) Bar(a)   // The function-like macro is named in the same way as a function.
273#else
274void Foo(int);
275#endif
276```
277
278Constant example:
279
280```c
281const int VERSION = 200;    // OK.
282
283const enum Color DEFAULT_COLOR = BLUE; // OK
284
285const char PATH_SEP = '/';  // OK
286
287const char * const GREETINGS = "Hello, World!"; // OK
288```
289
290Non-constant example:
291
292```c
293// A struct that does not meet the definition of constants
294const struct MyType g_myData = { ... };     // OK: Name it in lowerCamelCase style.
295
296// An array that does not meet the definition of constants
297const int g_xxxBaseValue[4] = { 1, 2, 4, 8 };   // OK: Name it in lowerCamelCase style.
298
299int Foo(...)
300{
301    // A local const variable that does not meet the definition of constants
302    const int bufSize = 100;    // OK: Name it in lowerCamelCase style.
303    ...
304}
305```
306
307Enum example:
308
309```c
310// Note: The enum type name is in the UpperCamelCase style, whereas the enumerated value is in uppercase letters separated by underscores (\_).
311enum BaseColor {
312    RED,
313    GREEN,
314    BLUE
315};
316```
317
318### <a name="a1-6"></a>Rec 1.5 Avoid temporary variables in function-like macros from polluting external scopes.
319
320**If possible, use a function instead of a function-like macro. Define a function-like macro only when necessary.**
321
322When defining local variables for a function-like macro, use double underscores at the end to avoid name conflicts with local variables in external functions. Example:
323```c
324#define SWAP_INT(a, b) do { \
325    int tmp__ = a; \
326    a = b; \
327    b = tmp__; \
328} while (0)
329```
330
331# <a name="c2"></a>2 Formatting
332
333## <a name="c2-1"></a>Line Length
334
335### <a name="r2-1"></a>Rule 2.1 Include 120 characters or less in each line.
336
337A longer line makes it more difficult for reading.
338To meet the line length requirement, you can shorten the names of functions and variables and reduce the number of nesting layers. This improves code readability.
339Unless a long line is necessary to maintain readability and present complete information, steer your document clear of long lines.
340Even on a high-resolution monitor, a long line increases the difficulty of reading. Strive for clearness and conciseness.
341
342Exceptions:
343
344- For code lines or comments, the use of the line feed causes content truncation and increases the search difficulty (grep).
345- The #include and #error statements are allowed to exceed the line length requirement. However, you should try to avoid this.
346
347Example:
348
349```c
350#ifndef XXX_YYY_ZZZ
351#error Header aaaa/bbbb/cccc/abc.h must only be included after xxxx/yyyy/zzzz/xyz.h
352#endif
353```
354
355## <a name="c2-2"></a>Indentation
356
357### <a name="r2-2"></a>Rule 2.2 Use spaces to indent and indent four spaces at a time.
358
359Only spaces can be used for indentation. Four spaces are indented each time. Do not use the Tab character to indent.
360Currently, almost all integrated development environments (IDEs) and code editors support automatic conversion of a Tab input to fours spaces. Configure your code editor to support indentation with spaces.
361
362## <a name="c2-3"></a>Braces
363
364### <a name="r2-3"></a>Rule 2.3 Use the K\&R indentation style.
365
366**K\&R style**
367While wrapping a line, the left brace of the function starts a new line and takes a single line. Other left braces are placed at the end of the line along with the statement.
368The right brace takes a single line, unless it is followed by the rest of the same statement, such as `while` in the `do` statement, `else` or `else if` in the `if` statement, a comma, or a semicolon.
369
370Example:
371
372```c
373struct MyType {     // Good: The left brace is placed at the end of the line along with the statement, and one space is used for indentation.
374    ...
375};                  // Good: The right brace is followed by the semicolon.
376
377int Foo(int a)
378{                   // Good: The left brace of the function starts a new line, and nothing else is placed on the line.
379    if (...) {
380        ...
381    } else {        // Good: The right brace is followed by the `else` statement.
382        ...
383    }               // Good: The right brace takes a single line.
384}
385```
386
387## <a name="c2-4"></a>Function Declaration and Definition
388
389### <a name="r2-4"></a>Rule 2.4 Keep the return type and function name of the function declaration or definition in the same line, and align the function parameter list appropriately if it needs to be wrapped.
390
391When a function is declared and defined, the return value type of the function should be in the same line as the function name.
392
393When the function parameter list is wrapped, it should be aligned appropriately.
394The left parenthesis of a parameter list is always in the same line as the function name. The right parenthesis always follows the last parameter.
395
396Example:
397
398```c
399ReturnType FunctionName(ArgType paramName1, ArgType paramName2)   // Good: All in one line
400{
401    ...
402}
403
404ReturnType VeryVeryVeryLongFunctionName(ArgType paramName1,     // Each added parameter starts on a new line because the line length limit is exceeded.
405                                        ArgType paramName2,     // Good: Aligned with the previous line
406                                        ArgType paramName3)
407{
408    ...
409}
410
411ReturnType LongFunctionName(ArgType paramName1, ArgType paramName2, // Parameters are wrapped because the line length limit is exceeded.
412    ArgType paramName3, ArgType paramName4, ArgType paramName5)     // Good: 4 spaces are used for indentation.
413{
414    ...
415}
416
417ReturnType ReallyReallyReallyReallyLongFunctionName(            // The line length cannot accommodate even the first parameter, and a line break is required.
418    ArgType paramName1, ArgType paramName2, ArgType paramName3) // Good: 4 spaces are used for indentation.
419{
420    ...
421}
422```
423
424## <a name="c2-5"></a>Function Calls
425
426### <a name="r2-5"></a>Rule 2.5 Align the parameter list appropriately if it needs to be wrapped.
427
428In a function call, if the function parameter list is wrapped, it should be aligned appropriately.
429The left parenthesis is always followed by a function name, and the right parenthesis always follows the last parameter.
430
431Example:
432
433```c
434ReturnType result = FunctionName(paramName1, paramName2);   // Good: Function parameters are placed in one line.
435
436ReturnType result = FunctionName(paramName1,
437                                 paramName2,                // Good: Aligned with the above parameters
438                                 paramName3);
439
440ReturnType result = FunctionName(paramName1, paramName2,
441    paramName3, paramName4, paramName5);                    // Good: 4 spaces are used for indentation.
442
443ReturnType result = VeryVeryVeryLongFunctionName(           // The line length cannot accommodate the first parameter, and therefore line feed is used.
444    paramName1, paramName2, paramName3);                    // 4 spaces are used for indentation.
445```
446
447If the parameters in a function call are associated with each other, you can group the parameters for better understanding, rather than strictly adhering to the formatting requirements.
448
449```c
450// Good: The parameters in each line represent a group of data structures with a strong correlation.They are placed on one line for ease of understanding.
451int result = DealWithStructureLikeParams(left.x, left.y,     // Indicates a group of parameters.
452                                         right.x, right.y);  // Indicates another group of related parameters.
453```
454
455## <a name="c2-6"></a>Conditional Statements
456
457### <a name="r2-6"></a>Rule 2.6 Use braces for conditional statements.
458
459Use braces to enclose conditional statements, even if there is only one statement.
460Reason:
461
462- Logic is intuitive and easy to read.
463- It is not easy to make mistakes when adding new code to the existing conditional statement.
464- Function-like macros without braces are used in conditional statements, can be error prone if braces do not surround the conditional statement.
465
466```c
467if (objectIsNotExist) {         // Good: Braces are added to a single-line conditional statement.
468    return CreateNewObject();
469}
470```
471
472### <a name="r2-7"></a>Rule 2.7 Do not place `if`, `else`, and `else if` in the same line.
473
474In a conditional statement, branches, if any, should be written in different lines.
475
476Good example:
477
478```c
479if (someConditions) {
480    ...
481} else {    // Good: The `else` statement is in a different line of `if`.
482    ...
483}
484```
485
486Bad example:
487
488```c
489if (someConditions) { ... } else { ... } // Bad: They are in the same line.
490```
491
492## <a name="c2-7"></a>Loops
493
494### <a name="r2-8"></a>Rule 2.8 Use braces for loop statements.
495
496Use braces to enclose the `for` and `while` statements, even if there is only one loop.
497
498```c
499for (int i = 0; i < someRange; i++) {   // Good: Braces are used.
500    DoSomething();
501}
502```
503
504```c
505while (condition) { }   // Good: The entire loop body is empty. And braces are used.
506```
507
508```c
509while (condition) {
510    continue;           // Good: The continue keyword highlights the end of the empty loop. And braces are used.
511}
512```
513
514Bad example:
515
516```c
517for (int i = 0; i < someRange; i++)
518    DoSomething();      // Bad: Braces should be added.
519```
520
521```c
522while (condition);      // Bad: The semicolon may be treated as part of the `while` statement.
523```
524
525## <a name="c2-8"></a>`switch` Statements
526
527### <a name="r2-9"></a>Rule 2.9 Indent the `case` or `default` statement in a `switch` statement block.
528
529Use the following indentation style for the `switch` statement:
530
531```c
532switch (var) {
533    case 0:             // Good: Indented
534        DoSomething1(); // Good: Indented
535        break;
536    case 1: {           // Good: Braces are added.
537        DoSomething2();
538        break;
539    }
540    default:
541        break;
542}
543```
544
545```c
546switch (var) {
547case 0:                 // Bad: 'case' not indented
548    DoSomething();
549    break;
550default:                // Bad: 'default' not indented
551    break;
552}
553```
554
555## <a name="c2-9"></a>Expressions
556
557### <a name="a2-1"></a>Rec 2.1 Keep a consistent line break style for expressions and ensure that operators are placed at the end of the line.
558
559A long expression that does not meet the line length requirement must be wrapped appropriately. Generally, the expression is wrapped after a lower-priority operator or a hyphen, and the operator or hyphen is placed at the end of the line, indicating that the operation is to be continued.
560
561Example:
562
563```c
564// Assume that the first line does not meet the line length requirement.
565if ((currentValue > MIN) &&  // Good: The Boolean operator is placed at the end of the line.
566    (currentValue < MAX)) {
567    DoSomething();
568    ...
569}
570
571int result = reallyReallyLongVariableName1 +    // Good: The plus sign is placed at the end of the line.
572             reallyReallyLongVariableName2;
573```
574
575After an expression is wrapped, ensure that the lines are properly aligned or indented by 4 spaces. Example:
576
577```c
578int sum = longVariableName1 + longVariableName2 + longVariableName3 +
579    longVariableName4 + longVariableName5 + longVariableName6;         // OK: indented with 4 spaces
580
581int sum = longVariableName1 + longVariableName2 + longVariableName3 +
582          longVariableName4 + longVariableName5 + longVariableName6;   // OK: aligned
583```
584
585## <a name="c2-10"></a>Variable Assignment
586
587### <a name="r2-10"></a> Rule 2.10 Do not write multiple variable definitions or assignment statements in one line.
588
589It is recommended that each line contain only one variable initialization statement, which is easier to read and understand.
590
591```c
592int maxCount = 10;
593bool isCompleted = false;
594```
595
596Bad example:
597
598```c
599int maxCount = 10; bool isCompleted = false; // Bad: Multiple initialization statements are placed in one line.
600int x, y = 0;  // Bad: Multiple variable definitions are placed in one line.Each definition occupies one line.
601
602int pointX;
603int pointY;
604...
605pointX = 1; pointY = 2;  // Bad: Multiple variable assignment statements are placed in one line.
606```
607
608Exceptions:
609If multiple variable definitions have strong correlation and do not need to be initialized, you can define the variables in a line for code compactness.
610
611```c
612int i, j;  // Good: Multiple variable definitions that do not need to be initialized are written in one line.
613for (i = 0; i < row; i++) {
614    for (j = 0; j < col; j++) {
615        ...
616    }
617}
618```
619
620## <a name="c2-11"></a>Initialization
621
622Initialization is applicable to structs, unions, and arrays.
623
624### <a name="r2-11"></a>Rule 2.11 Use indentation or make a reasonable alignment for a new line.
625
626For the struct or array initialization, use 4 spaces for indentation if a line break is made.
627From better readability, make a reasonable alignment.
628
629```c
630// Good: No line break for a short line.
631int arr[4] = { 1, 2, 3, 4 };
632
633// Good: A line break makes better readability.
634const int rank[] = {
635    16, 16, 16, 16, 32, 32, 32, 32,
636    64, 64, 64, 64, 32, 32, 32, 32
637};
638```
639
640For complex data, the initialization should be clear and compact.
641Refer to the following format:
642
643```c
644int a[][4] = {
645    { 1, 2, 3, 4 }, { 2, 2, 3, 4 }, // OK
646    { 3, 2, 3, 4 }, { 4, 2, 3, 4 }
647};
648
649int b[][8] = {
650    { 1, 2, 3, 4, 5, 6, 7, 8 },     // OK
651    { 2, 2, 3, 4, 5, 6, 7, 8 }
652};
653```
654
655```c
656int c[][8] = {
657    {
658        1, 2, 3, 4, 5, 6, 7, 8      // OK
659    }, {
660        2, 2, 3, 4, 5, 6, 7, 8
661    }
662};
663```
664
665Note:
666
667- If the left brace is placed at the end of the line, the corresponding right brace should be placed into a new line.
668- If the left brace is followed by the content, the corresponding right brace should also follow the content.
669
670### <a name="r2-12"></a>Rule 2.12 Initialize each member in a separate line during struct and union member initialization.
671
672The C99 standard supports the initialization of the struct and union members in their definition. This is called the designated initializer. In such a way, each member should be initialized in a separate line.
673
674```c
675struct Date {
676    int year;
677    int month;
678    int day;
679};
680
681struct Date date = {    // Good: When the designated initializer is used, each member is initialized in a separate line.
682    .year   = 2000,
683    .month  = 1,
684    .day    = 1
685};
686```
687
688## <a name="c2-12"></a>Pointers
689
690### <a name="a2-2"></a>Rec 2.2 Ensure that the asterisk (\*) in the pointer type is followed by the variable name or follows the type. There must be a space before or after the asterisk.
691
692When you declare or define a pointer variable or return a pointer type function, the asterisk can be placed on the left (following the type) or right (followed by the variable name). There must be only one space before or after the asterisk.
693
694```c
695int *p1;    // OK
696int* p2;    // OK
697
698int*p3;     // Bad: No space
699int * p4;   // Bad: Space on both sides
700```
701
702Choose a style and stay consistent.
703
704If you use the asterisk to follow the type, do not declare multiple variables with pointers in a line.
705
706```c
707int* a, b;  // Bad: b may be treated as a pointer.
708```
709
710Do not use the asterisk followed by the variable name if this style is not suitable in all cases.
711Keep style consistency first.
712
713```c
714char * const VERSION = "V100";      // OK
715int Foo(const char * restrict p);   // OK
716```
717
718Do not use the asterisk to follow the `const` or `restrict` keywords.
719
720## <a name="c2-13"></a>Compilation Preprocessing
721
722### <a name="r2-13"></a>Rule 2.13 Place the number sign (#) at the beginning of a line for compilation preprocessing. In nested compilation preprocessing, the number sign (#) can be indented.
723
724The number sign (#) must be placed at the beginning of a line for compilation preprocessing, even if the code is embedded in the function body.
725Try your best not to use compilation preprocessing macros. If they are needed in deed, they should be managed by dedicated personnel in a unified manner.
726
727## <a name="c2-14"></a>Whitespace
728
729### <a name="r2-14"></a>Rule 2.14 Use horizontal whitespaces to highlight keywords and important information, and avoid unnecessary whitespaces.
730
731Horizontal spaces should be used to highlight keywords and important information. Do not add spaces at the end of each line of code. The general rules are as follows:
732
733- Add spaces after keywords such as `if`, `switch`, `case`, `do`, `while`, and `for`.
734- Do not add spaces after the left parenthesis or before the right parenthesis.
735- Add a space before and after each binary operator (= + - \< > \* / % \| \& \^ \<= >= == !=).
736- Do not add a space after any unary operator (\& \* + - ~!).
737- Add a space before and after each ternary operator (? :).
738- Add spaces before and after the colon of bit field description.
739- Do not add spaces between ++/-- and variables.
740- Do not add spaces before and after the struct member operator (. ->).
741- Adding or not adding spaces inside the brace must be consistent.
742- Do not add spaces before commas, semicolons, or colons (excluding the colon in the ternary operator or the bit field description). Add spaces after them.
743- Do not add spaces between the parentheses of the function parameter list and the function name.
744- Do not add spaces between the parenthesis of the type cast and the object being converted.
745- Do not add spaces between the square bracket of the array and the array name.
746- Spaces at the end of the line can be omitted.
747
748For spaces inside the braces, the following **recommendations** are available:
749
750- It is recommended that spaces be added after the left brace and before the right brace.
751- For an empty constant or a constant with a single identifier or a single word, spaces are not required, for example, '{}', '{0}', '{NULL}', '{"hi"}'.
752- Spaces between consecutively nested multiple parentheses are not required, for example, '{{0}}', '{{ 1, 2 }}'. '{ 0, {1}}' is a bad example, since it is not a consecutively nested scene and the spaces inside the outermost braces are inconsistent.
753
754In normal cases:
755
756```c
757int i = 0;                  // Good: When the variable is initialized, there should be spaces before and after the =. Do not leave a space before the semicolon.
758int buf[BUF_SIZE] = {0};    // Good: For array initialization, spaces in curly braces are optional.
759int arr[] = { 10, 20 };     // Good: A space is added before and after the brace.
760```
761
762Function definition and call:
763
764```c
765int result = Foo(arg1,arg2);
766                      ^         // Bad: There is no space after the comma.
767
768int result = Foo( arg1, arg2 );
769                 ^          ^   // Bad: No space should be added to either side in the parentheses.
770```
771
772Pointer and address-of operator:
773
774```c
775x = *p;     // Good: There is no space between the operator (*) and the pointer p.
776p = &x;     // Good: There is no space between the operator (&) and the variable x.
777x = r.y;    // Good: When a member variable is accessed through the operator (.), no space is added.
778x = r->y;   // Good: When a member variable is accessed through the operator (->), no space is added.
779```
780
781Operator:
782
783```c
784x = 0;    // Good: There is a space before and after the assignment operator (=).
785x = -5;   // Good: There is no space between the minus sign (-) and the number.
786++++x; // Good: There is no space between ++/-- and the variable.
787x--;
788
789if (x && !y)        // Good: There is a space before and after the Boolean operator, and there is no space between the operator (!) and variable.
790v = w * x + y / z;  // Good: There is a space before and after binary operators.
791v = w * (x + z);    // Good: There is no space before and after the expression in the parentheses.
792```
793
794Loops and conditional statements:
795
796```c
797if (condition) {    // Good: A space is added between the `if` keyword and the parenthesis, and no space is added before or after the conditional statement inside the parentheses.
798    ...
799} else {            // Good: A space is added between the `else` keyword and the curly brace.
800    ...
801}
802
803while (condition) {}    // Good: A space is added between the `while` keyword and the parenthesis, and no space is added before or after the conditional statement inside the parentheses.
804
805for (int i = 0; i < someRange; ++i) {  // Good: A space is added between the `for` keyword and the parenthesis, and after the semicolons (;).
806    ...
807}
808
809switch (var) {  // Good: A space is added after the `switch` keyword.
810    case 0:     // Good: No space is added between the `case` conditional statement and the colon (:).
811        ...
812        break;
813    ...
814    default:
815        ...
816        break;
817}
818```
819
820Note: The current IDE and code editor can be set to delete spaces at the end of a line. Configure your editor correctly.
821
822### <a name="a2-3"></a>Rec 2.3 Arrange blank lines reasonably to keep the code compact.
823
824Reduce unnecessary blank lines so that more code can be displayed for easy reading. The following rules are recommended:
825
826- Make a reasonable arrangement of blank lines according to the degree of relevance of neighboring content.
827- Do not put two or more consecutive blank lines inside a function, a type definition, a macro, or an initialization expression.
828- Do not use **three** or more consecutive blank lines.
829- Do not add blank lines at the start and end of a code block defined by braces.
830
831```c
832ret = DoSomething();
833
834if (ret != OK) {    // Bad: Return value judgment should follow the function call.
835    return -1;
836}
837```
838
839```c
840int Foo(void)
841{
842    ...
843}
844
845
846
847int Bar(void)       // Bad: Use no more than two continuous blank lines.
848{
849    ...
850}
851```
852
853```c
854int Foo(void)
855{
856
857    DoSomething();  // Bad: The blank lines above and below are unnecessary.
858    ...
859
860}
861```
862
863# <a name="c3"></a>3 Comments
864
865Generally, clear architecture and good symbol naming are recommended to improve code readability, and comments are provided only when necessary.
866Comments help readers quickly understand code. Therefore, **comments should be provided when necessary** for the sake of readers.
867
868The comments must be concise, clear, and unambiguous, ensuring that the information is complete and not redundant.
869
870**Comments are as important as code.**
871When writing a comment, you need to step into the reader's shoes and use comments to express what the reader really needs. Comments are used to express the code functionality and intention, rather than repeating code.
872When modifying the code, ensure that the comments are consistent. It is impolite to only modify code and not update the comments. This destroys the consistency between code and comments, and may cause confusion or even misleading.
873
874Comment code in fluent **English**.
875
876Comments must be added in the following scenarios (including but not limited to the listed scenarios):
8771. Functions in the external interface header file provided by the module
8782. Global variables being defined
8793. Core algorithms
8804. A function that contains more than 50 lines
881
882## <a name="c3-1"></a>Comment Style
883
884In C code, both `/*` `*/` and `//` can be used.
885Comments can be classified into different types depending on the purpose and position, such as file header comments, function header comments, and general comments.
886Comments of the same type must keep a consistent style.
887
888Note: The sample code used in this article sees extensive use of the '//' post-comment. This is only for better understanding, and does not mean that this comment style is better.
889
890## <a name="c3-2"></a>File Header Comments
891
892### <a name="r3-1"></a>Rule 3.1 Include the copyright license in the file header comments.
893
894/\*
895
896* Copyright (c) 2020 Huawei Device Co., Ltd.
897* Licensed under the Apache License, Version 2.0 (the "License");
898* you may not use this file except in compliance with the License.
899* You may obtain a copy of the License at
900*
901* http://www.apache.org/licenses/LICENSE-2.0
902*
903* Unless required by applicable law or agreed to in writing, software
904* distributed under the License is distributed on an "AS IS" BASIS,
905* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
906* See the License for the specific language governing permissions and
907* limitations under the License. \*/
908
909## <a name="c3-3"></a>Function Header Comments
910
911### <a name="r3-2"></a>Rule 3.2 Do not use empty function header comments with no content.
912
913Not all functions need function header comments.
914Function header comments must be added for any information that cannot be expressed just with function prototype.
915
916Function header comments are placed above the function declaration or definition.
917Select and use one of the following styles:
918**Use '//' to start the function header.**
919
920```c
921// Single-line function header
922int Func1(void);
923
924// Multi-line function header
925// Second line
926int Func2(void);
927```
928
929**Use '/\*' '\*/' to start the function header.**
930
931```c
932/* Single-line function header */
933int Func1(void);
934
935/*
936 * Single-line or multi-line function header
937 * Second line
938 */
939int Func2(void);
940```
941
942Use function names to describe functions, and only add function header comments if necessary.
943Do not write useless or redundant function headers. Do not write empty function headers with no content.
944
945The following content is **optional** in the function header comment: function description, return value, performance constraint, usage, memory convention, algorithm implementation, and reentering requirement.
946In the function interface declaration in the external header file of the module, the function header comment should clearly describe important and useful information.
947
948Example:
949
950```c
951/*
952 * The number of written bytes is returned. If -1 is returned, the write operation fails.
953 * Note that the memory buffer is released by the caller.
954 */
955int WriteString(char *buf, int len);
956```
957
958Bad example:
959
960```c
961/*
962 * Function name: WriteString
963 * Function: Write a character string.
964 * Parameter:
965 * Return value:
966 */
967int WriteString(char *buf, int len);
968```
969
970Problems in the preceding example are as follows:
971
972- The 'Parameter' and 'Return value' headings have no content.
973- The function name has redundant information.
974- It does not clearly state the party that should release the buffer.
975
976## <a name="c3-4"></a>Code Comments
977
978### <a name="r3-3"></a>Rule 3.3 Place code comments above or to the right of the code.
979
980### <a name="r3-4"></a>Rule 3.4 Add a space between the comment character and the comment content, and one space between the comment and code if the comment is placed to the right of the code.
981
982Comments placed above code should be indented to the same level as the code.
983Select and use one of the following styles:
984**Use '//' to start the comment.**
985
986```c
987// Single-line comment
988DoSomething();
989
990// Multi-line comment
991// Second line
992DoSomething();
993```
994
995**Use '/\*' '\*/' to start the comment.**
996
997```c
998/* Single-line comment */
999DoSomething();
1000
1001/*
1002 * Single-/Multi-line comment
1003 * Second line
1004 */
1005DoSomething();
1006```
1007
1008Leave at least one space between the code and the comment on the right. No more than four spaces is recommended.
1009You can use the extended Tab key to indent 1-4 spaces.
1010
1011Select and use one of the following styles:
1012
1013```c
1014int foo = 100;  // Comment on the right
1015int bar = 200;  /* Comment on the right */
1016```
1017
1018It is more appealing sometimes when the comment is placed to the right of code and the comments and code are aligned vertically.
1019After the alignment, ensure that the comment is 1–4 spaces separated from the closest code line on the left.
1020Example:
1021
1022```c
1023#define A_CONST 100         /* Related comments of the same type can be aligned vertically. */
1024#define ANOTHER_CONST 200   /* Leave spaces after code to align comments vertically. */
1025```
1026
1027If the comment on the right exceeds the permitted line length, the comment can be placed above the code.
1028
1029### <a name="r3-5"></a>Rule 3.5 Delete unused code segments. Do not comment them out.
1030
1031Code that is commented out cannot be maintained. If you attempt to restore the code, it is very likely to introduce ignorable defects.
1032The correct method is to delete unnecessary code. If necessary, consider porting or rewriting the code.
1033
1034Here, commenting out refers to the removal of code from compilation without actually deleting it. This is done by using /\* \*/, //, #if 0, #ifdef NEVER\_DEFINED, and so on.
1035
1036### <a name="a3-1"></a>Rec 3.1 Provide comments if `break` or `return` is not added to the end of the `case` statement block (fall-through).
1037
1038Sometimes, the same thing is needed for multiple `case` tags. When a `case` statement ends without `break` or `return`, the statement in the next `case` tag will be executed.This is called "fall-through".
1039In this case, add comments for the "fall-through" to clearly express your intention, or at least explicitly specify the "fall-through".
1040
1041For example, to explicitly specify the "fall-through":
1042
1043```c
1044switch (var) {
1045    case 0:
1046        DoSomething();
1047        /* fall-through */
1048    case 1:
1049        DoSomeOtherThing();
1050        ...
1051        break;
1052    default:
1053        DoNothing();
1054        break;
1055}
1056```
1057
1058If the `case` statement is empty, no comment is required to explain the "fall-through".
1059
1060```c
1061switch (var) {
1062    case 0:
1063    case 1:
1064        DoSomething();
1065        break;
1066    default:
1067        DoNothing();
1068        break;
1069}
1070```
1071
1072# <a name="c4"></a>4 Header Files
1073
1074**For the C programming language, the design of the header file reflects most of the system design.**
1075The correct use of the header file makes code more readable, reduces file size, and speeds up compilation and build performance.
1076
1077The following programming specifications aim to help you properly plan header files.
1078
1079## <a name="c4-1"></a>Header File Responsibility
1080
1081A header file is an external interface of a module or file.
1082The interface declaration for most functions (except inline functions) is suitable in the header file. Interface implementations are not allowed in the header file.
1083Header responsibility should be simple. A complex header file will make dependencies complex and cause a long compilation time.
1084
1085### <a name="a4-1"></a>Rec 4.1 For each .c file, provide a corresponding .h file, which is used to declare the interfaces that need to be provided externally.
1086
1087Generally, each .c file has a corresponding .h file (not necessarily with the same name), which is used to store the function declarations, macro definitions, and type definitions that are to be exposed externally.
1088If a .c file does not need to open any interface externally, it should not exist.
1089
1090Exceptions: the entry point of the program (for example, the file where the main function is located), unit test code, and dynamic library code.
1091
1092Example:
1093Content of **foo.h**:
1094
1095```c
1096#ifndef FOO_H
1097#define FOO_H
1098
1099int Foo(void);  // Good: Declare an external interface in the header file.
1100
1101#endif
1102```
1103
1104Content of **foo.c**:
1105
1106```c
1107static void Bar(void);  // Good: The declaration of the internal function is placed in the header of the .c file, declaring its static scope.
1108
1109void Foo(void)
1110{
1111    Bar();
1112}
1113
1114static void Bar(void)
1115{
1116    // Do something;
1117}
1118```
1119
1120Internally used functions declarations, macros, enums, structs, and others should not be placed in header files.
1121
1122In some products, one .c file corresponds to two .h files. One is used to store external public interfaces, and the other is used to store definitions and declarations among others for internal use to limit the number of code lines in the .c file.
1123This style is not recommended. It is used only because the .c file is too large. You should consider splitting the .c file first.
1124In addition, if private definitions and declarations are placed in independent header files, they technically cannot avoid inclusion.
1125
1126This rule, in turn, is not necessarily correct. Example:
1127Some simple header files, such as the command ID definition header file, do not need to have the corresponding .c file.
1128If a set of interface protocols has multiple instances and the interface is fixed, one .h file can have multiple .c files.
1129
1130### <a name="a4-2"></a>Rec 4.2 Use .h as the extension of the header file, rather than other unconventional extensions, for example, .inc.
1131
1132Some products use .inc as the header file name extension, which does not comply with the C programming language.A header file using .inc as the file name extension usually indicates a private header file. However, in practice, this recommendation is not followed properly. An .inc file is generally contained in multiple .c files. It is not recommended that private definitions be stored in header files. For details, see [Rec 4.1](#a4-1).
1133
1134## <a name="c4-2"></a>Header File Dependency
1135
1136The header file contains a dependency, and the dependency should be stable.
1137Generally, an unstable module depends on a stable module. When the unstable module changes, the build of the stable module is not affected.
1138
1139Dependency direction is as follows: Products depend on the platform, and the platform depends on the standard library.
1140
1141In addition to unstable modules depending on stable modules, each module depends on the interface. In this way, in case of any internal implementation changes to one module, users do not need to recompile another module.
1142It is assumed that the interface is the most stable.
1143
1144### <a name="r4-1"></a>Rule 4.1 Forbid cyclic dependency of header files.
1145
1146Cyclic dependency (also known as a circular dependency) of header files means that a.h contains b.h, b.h contains c.h, and c.h contains a.h. If any header file is modified, all code containing a.h, b.h, and c.h needs to be recompiled.
1147For a unidirectional dependency: a.h contains b.h, b.h contains c.h, and c.h does not contain any header file, modifying a.h does not mean a need to recompile the source code for b.h or c.h.
1148
1149The cyclic dependency of header files reflects an obviously unreasonable architecture design, which can be avoided through optimization.
1150
1151### <a name="r4-4"></a>Rule 4.2 Include the internal #include protection character (#define protection) in the header file.
1152
1153To prevent header files from being included multiple times, all header files should be protected by #define. Do not use #pragma once.
1154
1155When defining a protection character, comply with the following rules:
1156
1157- Use a unique name for the protection character in the format of subsystem\_component\_file.
1158- Do not place code or comments before or after the protected part, except for file header comments.
1159
1160Assume that the **timer.h** file of the timer component of the util subsystem is stored in the **timer/include/timer.h** directory. If `TIME_H` is used as the protection character, name conflicts may occur. Use the following protection characters instead:
1161```c
1162#ifndef UTIL_TIMER_TIMER_H
1163#define UTIL_TIMER_TIMER_H
1164
1165...
1166
1167#endif // UTIL_TIMER_TIMER_H
1168```
1169
1170### <a name="r4-5"></a>Rule 4.3 Do not reference external function interfaces and variables by using declaration.
1171
1172You can use the interfaces provided by other modules or files only by using header files.
1173Using external function interfaces and variables with an extern declaration may cause inconsistency between declarations and definitions when external interfaces are changed.
1174In addition, this kind of implicit dependency may cause architecture corruption.
1175
1176Cases that do not comply with specifications:
1177Content of **a.c**:
1178
1179```c
1180extern int Foo(void);   // Bad: Reference external functions by using the extern declaration.
1181void Bar(void)
1182{
1183    int i = Foo();  // Here, the external interface Foo is used.
1184    ...
1185}
1186```
1187
1188It should be changed to:
1189Content of **a.c**:
1190
1191```c
1192#include "b.h"      // Good: Use the interfaces provided by another .c file by including the header file.
1193void Bar(void)
1194{
1195    int i = Foo();
1196    ...
1197}
1198```
1199
1200Content of **b.h**:
1201
1202```c
1203int Foo(void);
1204```
1205
1206Content of **b.c**:
1207
1208```c
1209int Foo(void)
1210{
1211    // Do something
1212}
1213```
1214
1215In some scenarios, if internal functions need to be referenced with no intrusion to the code, the extern declaration mode can be used.
1216Example:
1217When performing unit testing on an internal function, you can use the extern declaration to reference the tested function.
1218When a function needs to be stubbed or patched, the function can be declared using extern.
1219
1220### <a name="r4-6"></a>Rule 4.4 Do not include header files in extern "C".
1221
1222If a header file is included in extern "C", extern "C" may be nested. Some compilers restrict the number of nesting layers of extern "C". Too many nesting layers may cause compilation errors.
1223
1224extern "C" usually occurs in mixed programming using both C and C++. If extern "C" includes a header file, the original intent behind the header file may be hindered, for example, when linkage specifications are changed incorrectly.
1225
1226Assume that there are two header files: **a.h** and **b.h**.
1227Content of **a.h**:
1228
1229```c
1230...
1231#ifdef __cplusplus
1232void Foo(int);
1233#define A(value) Foo(value)
1234#else
1235void A(int)
1236#endif
1237```
1238
1239Content of **b.h**:
1240
1241```c
1242...
1243#ifdef __cplusplus
1244extern "C" {
1245#endif
1246
1247#include "a.h"
1248void B(void);
1249
1250#ifdef __cplusplus
1251}
1252#endif
1253```
1254
1255When you use the C++ preprocessor to expand **b.h**, the following information is displayed:
1256
1257```c
1258extern "C" {
1259    void Foo(int);
1260    void B(void);
1261}
1262```
1263
1264In the **a.h** file, the **Foo** function is intended to be a C++ free function following the C++ specifications. However, in the **b.h** file, because `#include "a.h"` is placed inside `extern "C"`, the linking specification of the **Foo** function is changed incorrectly.
1265
1266Exceptions: In the C++ compilation environment, if you want to reference a header file written in pure C, a non-intrusive approach is to exclude the C header file from `extern "C"`.
1267
1268# <a name="c5"></a>5 Functions
1269
1270Functions help avoid repeated code and increase reusability. Functions are layered to reduce complexity and hide implementation details, making programs more modular and facilitating code reading and maintenance.
1271
1272Functions should be concise and short.
1273One function completes only one thing.
1274
1275## <a name="c5-1"></a>Function Design
1276
1277The essence of function design is to write clean functions and organize code effectively.The code should be simple and not conceal the designer's intention, using clean abstractions and straightforward control statements to organize the function naturally.
1278
1279### <a name="r5-1"></a>Rule 5.1 Avoid long functions and ensure that functions contain no more than 50 lines (excluding blank lines and comments).
1280
1281A function should be able to be displayed on one screen (fewer than 50 lines). It does only one thing and does it well.
1282
1283A long function usually means that it aims to implement complex functionalities or contains excess details.
1284
1285Exceptions:
1286Considering the code's aggregation and functionality, some functions may exceed 50 lines, but only if the code is readable and concise.
1287These exceptions should be minimal, such as specific algorithm processing.
1288
1289Even if a large function works well in the moment, once someone modifies it, new problems may occur. It may even cause bugs that are difficult to discover.
1290It is recommended that you split the code into several functions that are simpler and easier to manage so that others can easily read and modify the code.
1291
1292### <a name="r5-2"></a>Rule 5.2 Avoid nesting a code block more than four times within a function.
1293
1294The nested code block depth of a function refers to the layered depth of a code control block (created by statements such as `if`, `for`, `while`, and `switch`).
1295Each layer of nesting increases the difficulty in reading the code.
1296Further functional decomposition should be done for better understanding.
1297
1298Using `guard clauses` can effectively reduce the nesting layers of the `if` statements. Example:
1299Three nesting layers are used originally:
1300
1301```c
1302int Foo(...)
1303{
1304    if (received) {
1305        type = GetMsgType(msg);
1306        if (type != UNKNOWN) {
1307            return DealMsg(...);
1308        }
1309    }
1310    return -1;
1311}
1312```
1313
1314Two nesting layers after code reconstruction using `guard clauses`:
1315
1316```c
1317int Foo(...)
1318{
1319    if (!received) {    // Good: Use the 'guardian statement'.
1320        return -1;
1321    }
1322
1323    type = GetMsgType(msg);
1324    if (type == UNKNOWN) {
1325        return -1;
1326    }
1327
1328    return DealMsg(..);
1329}
1330```
1331
1332Exceptions:
1333Considering the code's aggregation and functionality, some functions may contain 4 or more nesting layers, but only if the code is readable and concise.
1334These exceptions should be rare.
1335
1336### <a name="a5-1"></a>Rec 5.1 Process all returned error codes.
1337
1338A function (in a standard library, a third-party library, or a user-defined function) must be able to indicate errors. This can be done by using error tags, special return data, or other means. No matter when a function provides such a mechanism, the caller should immediately check the error indication after the function returns.
1339
1340Example:
1341
1342```c
1343char fileHead[128];
1344ReadFileHead(fileName, fileHead, sizeof(fileHead)); // Bad: The return value is not checked.
1345
1346DealWithFileHead(fileHead, sizeof(fileHead));       // The 'fileHead' is possibly invalid.
1347```
1348
1349The correct format is as follows:
1350
1351```c
1352char fileHead[128];
1353ret = ReadFileHead(fileName, fileHead, sizeof(fileHead));
1354if (ret != OK) {                // Good: Ensure that the 'fileHead' is written.
1355    return ERROR;
1356}
1357
1358DealWithFileHead(fileHead, sizeof(fileHead));       // Process the file header.
1359```
1360
1361If the return value of a function is ignored and `void` is returned frequently, check whether the return value of the function is designed properly.
1362Only if the caller of a function really doesn't need a return value, should you design the function to return `void`.
1363
1364## <a name="c5-2"></a>Function Parameters
1365
1366### <a name="a5-2"></a>Rec 5.2 Use the return value instead of the output parameter when designing a function.
1367
1368Using return values rather than output parameters improves readability and usually provides the same or better performance.
1369
1370Readability can be improved by naming functions such as GetXxx, FindXxx, IsXxx, OnXxx, or directly using a single noun, to directly return the corresponding object.
1371
1372Exceptions:
13731. When multiple values are returned, you can design an output parameter for the function.
13742. If memory allocation is involved, you can design an output parameter. The caller passes the allocated memory as an output parameter, and memory allocation is not performed in the function.
1375
1376### <a name="a5-3"></a>Rec 5.3 Define function parameters in the sequence of input, output, and input/output parameters.
1377
1378You are advised to define function parameters in the sequence of input, output, and input/output parameters.
1379
1380### <a name="r5-3"></a>Rule 5.3 Provide a release function if allocation of resources, such as memory, locks, and queues, is involved.
1381
1382Resources should be released from where they are applied for. If a function applies for resources, the module must provide resource functions.
1383
1384### <a name="a5-4"></a>Rec 5.4 Use strongly typed parameters. Do not use void\*.
1385
1386While different languages have their own views on strong typing and weak typing, it is generally believed that C/C++ is a strongly typed language. Since we use such a strongly typed language, we should keep this style.
1387The advantage of this strongly typed style is to prevent evasive errors by catching errors at the compilation stage.
1388
1389Strong types help the compiler find more errors.Pay attention to the usage of the `FooListAddNode` function in the following code:
1390
1391```c
1392struct FooNode {
1393    struct List link;
1394    int foo;
1395};
1396
1397struct BarNode {
1398    struct List link;
1399    int bar;
1400}
1401
1402void FooListAddNode(void *node) // Bad: Here, the void * type is used to pass parameters.
1403{
1404    FooNode *foo = (FooNode *)node;
1405    ListAppend(&g_fooList, &foo->link);
1406}
1407
1408void MakeTheList(...)
1409{
1410    FooNode *foo;
1411    BarNode *bar;
1412    ...
1413
1414    FooListAddNode(bar);        // Wrong: In this example, the bar parameter rather than the foo parameter is passed.No error is reported immediately and issues may occur as a result.
1415}
1416
1417```
1418
1419The preceding problems may be difficult to expose and are more destructive than compiler errors.
1420If the parameter type of `FooListAddNode` is specified clearly, instead of with the `void *` type, the preceding problem can be detected during compilation.
1421
1422```c
1423void FooListAddNode(FooNode *foo)
1424{
1425    ListAppend(&g_fooList, &foo->link);
1426}
1427```
1428
1429Exceptions: For some generic interfaces, you can use the input parameter `void *` to pass different types of pointers.
1430
1431### <a name="a5-5"></a>Rec 5.5 It is the caller's responsibility to check the validity of internal function parameters of a module.
1432
1433Validity check must be performed on parameters passed from external modules to protect programs from being damaged by invalid input data.
1434When calling internal functions, by default, the caller is responsible for ensuring the validity of any returned data. If the callee takes responsibility for checking data validity, checks may be performed multiple times and redundant code is generated. This is not concise.
1435
1436When the caller ensures the validity of any received data, this contractual programming makes logic simpler and code more readable.
1437Example:
1438
1439```c
1440int SomeProc(...)
1441{
1442    int data;
1443
1444    bool dataOK = GetData(&data);       // Get data.
1445    if (!dataOK) {                      // Check the result of the previous step to ensure data validity.
1446        return -1;
1447    }
1448
1449    DealWithData(data);                 // Call the data processing function.
1450    ...
1451}
1452
1453void DealWithData(int data)
1454{
1455    if (data < MIN || data > MAX) {     // Bad: The caller has already ensured data validity.
1456        return;
1457    }
1458
1459    ...
1460}
1461```
1462
1463### <a name="a5-5"></a>Rec 5.5 Declare the pointer argument of a function as 'const' if it is not used to modify the pointed object.
1464
1465The const pointer argument, which restricts the function from modifying the object through the pointer, makes code stronger and safer.
1466
1467Example: In the example of the strncmp in the 7.21.4.4 of the C99 standard, the invariant parameter is declared as const.
1468
1469```c
1470int strncmp(const char *s1, const char *s2, size_t n); // Good: The invariant parameter is declared as const.
1471```
1472
1473Note: Whether to declare the pointer parameter as `const` depends on the function design, but not on whether there is a "modify object" action in the function entity.
1474
1475### <a name="a5-6"></a>Rec 5.6 Include no more than 5 parameters in a function.
1476
1477If a function has too many parameters, the function is easy to be affected by changes in external code, hindering maintenance. Too many function parameters will also increases the workload for testing.
1478
1479The number of parameters in a function must not exceed 5. If the number of parameters exceeds 5, consider the following:
1480
1481- Check whether the function can be split.
1482- Check whether any related parameters can be combined and defined as a struct.
1483
1484## <a name="c5-3"></a>Inline Functions
1485
1486An inline function is a function optimization method introduced by C99. Function inlining can eliminate the overhead of function calls; thanks to inlining, combination with the called code is implemented, so that the compiler can achieve further code optimization from a larger perspective. The inline function is similar to a function-like macro. For details, see [Rec 6.1](#rec-61-use-functions-instead-of-function-like-macros).
1487
1488### <a name="a5-7"></a>Rec 5.7 Include no more than 10 lines in an inline function (excluding blank lines and comments).
1489
1490Defining a function as an inline function generally aims to improve performance, though it may fail to do so.If the function body is short, function inlining can effectively reduce the size of the target code and improve the function execution efficiency.
1491Vice versa, if the function body is large, inlining will cause expansion of the target code, especially when there are many call points.
1492It is recommended that inline functions be controlled to within **10** lines.
1493
1494Do not abuse inline functions to improve performance. Avoid premature optimization. In general, a function can be defined as an inline function only when actual test data proves that the inlining achieves higher performance. Functions such as setter and getter functions, which are short and called frequently, can be defined as inline functions.
1495
1496### <a name="r5-3"></a>Rule 5.3 Define inline functions that will be called by multiple source files in the header file.
1497
1498Inline functions are unfolded in compilation. Therefore, the inline function definition must be visible in each source file that calls this function.
1499As shown in the following code, **inline.h** contains the declaration of the `SomeInlineFunc` function but not the definition. The **other.c** file includes **inline.h**. As a result, inlining fails when `SomeInlineFunc` is called.
1500
1501inline.h
1502
1503```c
1504inline int SomeInlineFunc(void);
1505```
1506
1507inline.c
1508
1509```c
1510inline int SomeInlineFunc(void)
1511{
1512    // Implementation code
1513}
1514```
1515
1516other.c
1517
1518```c
1519#include "inline.h"
1520int OtherFunc(void)
1521{
1522    int ret = SomeInlineFunc();
1523}
1524```
1525
1526Due to this restriction, if multiple source files need to call the same inline function, the definition of the inline function must be placed in the header file.
1527The inline function implementation in **gnu89** differs from that in the **C99** standard. For compatibility, you can declare the function as **static inline**.
1528
1529# <a name="c6"></a>6 Macros
1530
1531## <a name="c6-1"></a>Function-like Macros
1532
1533A function-like macro is a macro (as shown in the following example) similar to a function. It contains several statements to implement a specific function.
1534
1535```c
1536#define ASSERT(x) do { \
1537    if (!(x)) { \
1538        printk(KERN_EMERG "assertion failed %s: %d: %s\n", \
1539              __FILE__, __LINE__, #x); \
1540        BUG(); \
1541    } \
1542} while (0)
1543```
1544
1545### <a name="a6-1"></a>Rec 6.1 Use functions instead of function-like macros.
1546
1547Before defining a function-like macro, consider whether it can be replaced with a function. If yes, you are advised to use a function for replacement.
1548The disadvantages of the function-like macro are as follows:
1549
1550- Function-like macros haves no type check, which is not as strict as the function call check. For the example code, see [Below](#macro_lack_of_type_check__example).
1551- If macro parameters are not calculated during macro expansion, unexpected results may be generated. For details, see [Rule 6.1](#rule-61-use-complete-parentheses-for-macro-parameters-when-defining-a-macro) and [Rule 6.3](#rule-63-do-not-pass-expressions-with-side-effects-to-a-function-like-macro).
1552- A macro has no independent scope. When it is used together with control flow statements, unexpected results described in [Rule 6.2](#rule-62-place-implementation-statements-of-function-like-macros-that-contain-multiple-statements-in-a-do-while0) may be generated.
1553- There are high skill requirements on the proper use of macros (for example, the usage of `#` and wide use of parentheses), which reduces readability.
1554- Extensions of some macros can only be implemented by specific compilers in specific scenarios, such as `statement expression` of `gcc`, reducing the portability.
1555- After the macro is expanded during precompilation, it is invisible during subsequent compilation, linking, and debugging. Besides, macros that contain multiple lines are expanded into a line.
1556- Macros containing a large number of statements must be expanded at each call point. If there are many call points, the code will be expanded.
1557
1558<a name="macro_lack_of_type_check__example"></a>Example code of a function-like macro lacking type check:
1559
1560```c
1561#define MAX(a, b)   (((a) < (b)) ? (b) : (a))
1562
1563int Max(int a, int b)
1564{
1565    return (a < b) ? b : a;
1566}
1567
1568int TestMacro(void)
1569{
1570    unsigned int a = 1;
1571    int b = -1;
1572
1573    (void)printf("MACRO: max of a(%u) and b(%d) is %d\n", a, b, MAX(a, b));
1574    (void)printf("FUNC : max of a(%u) and b(%d) is %d\n", a, b, Max(a, b));
1575    return 0;
1576}
1577```
1578
1579Due to the lack of type check, the comparison between `a` and `b` in `MAX` is changed to a comparison ignoring the sign status. The result is **a \< b**. The output is as follows:
1580
1581```
1582MACRO: max of a(1) and b(-1) is -1
1583FUNC : max of a(1) and b(-1) is 1
1584```
1585
1586The function does not have the preceding macro disadvantages. However, compared with macros, the biggest disadvantage of functions is its low execution efficiency (increasing the overhead of function calls and the difficulty of compiler optimization).
1587Therefore, the C99 standard introduces inline functions (gcc introduces inline functions ahead of this standard).
1588
1589The inline function is similar to the macro, as it is also expanded at the call point. The difference is that inline functions are expanded during compilation.
1590Inline functions have the advantages of both functions and macros:
1591
1592- Strict type checking is performed for inline functions and functions.
1593- Each input parameter of an inline function or function is calculated only once.
1594- Inline functions are unfolded in place and there is no overhead for function calls.
1595- Inline functions are better optimized than standard functions.
1596
1597For performance-sensitive code, consider using inline functions instead of function-like macros.
1598Functions and inline functions cannot completely replace function-like macros, since function-like macros are more suitable for certain scenarios.
1599For example, in a log scenario, using a function-like macro with variable parameters and default parameters is more convenient.
1600
1601```c
1602int ErrLog(const char *file, unsigned long line, const char *fmt, ...);
1603#define ERR_LOG(fmt, ...) ErrLog(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
1604```
1605
1606### <a name="r6-1"></a>Rule 6.1 Use complete parentheses for macro parameters when defining a macro.
1607
1608The macro parameter is replaced by text only when the macro is expanded. The value is calculated when the macro is compiled. After the text replacement, the statements contained in the macro are combined with called code.
1609The expression after combination may result in a different result than expected, especially when the macro parameter is in an expression.
1610
1611The following is an incorrect format:
1612
1613```c
1614#define SUM(a, b) a + b         // Bad
1615```
1616
1617When the macro is used, the execution result is inconsistent with the expected result.
1618`100 / SUM(2, 8)` is expanded to `(100 / 2) + 8`. The expected result is `100 / (2 + 8)`.
1619This problem can be solved by adding parentheses to the entire expression, as shown in the following:
1620
1621```c
1622#define SUM(a, b) (a + b)       // Bad
1623```
1624
1625However, this method has the following problems:
1626`SUM(1 << 2, 8)` is extended to `1 << (2 + 8)` (because the priority of `<<` is lower than that of `+`), which is inconsistent with the expected result `(1 << 2) + 8`.
1627
1628To solve this problem, add parentheses to each macro parameter, as shown in the following:
1629
1630```c
1631#define SUM(a, b) (a) + (b)     // Bad
1632```
1633
1634The third scenario is as follows: `SUM(2, 8) * 10` . The result after the extension is `(2) + ((8) * 10)`, which is inconsistent with the expected result `(2 + 8) * 10`.
1635
1636In conclusion, the correct format is as follows:
1637
1638```c
1639#define SUM(a, b) ((a) + (b))   // Good.
1640```
1641
1642Avoid abusing parentheses. As shown in the following, adding parentheses to a single identifier or a positive number is meaningless.
1643
1644```c
1645#define SOME_CONST      100     // Good: No parentheses needed for a single positive number.
1646#define ANOTHER_CONST   (-1)    // Good: Parentheses needed for a negative number.
1647
1648#define THE_CONST SOME_CONST    // Good: No parentheses needed for a single identifier.
1649```
1650
1651Notes:
1652
1653- Do not add parentheses to macro parameters when they are involved in the '#' or '##' operation.
1654- Do not add parentheses to macro parameters when they are used for string concatenation.
1655- If a macro parameter is used as a separate part in one side of an assignment expression (including +=, -=, etc.), parentheses are not required.
1656- If a macro parameter is used as a separate part in comma expressions, functions or macro call lists, parentheses are not required.
1657
1658Example:
1659
1660```c
1661#define MAKE_STR(x) #x                  // No parentheses for 'x'
1662
1663#define HELLO_STR(obj) "Hello, " obj    // No parentheses for 'obj'
1664
1665#define ADD_3(sum, a, b, c) (sum = (a) + (b) + (c)) // 'a', 'b', and 'c' need parentheses, whereas 'sum' does not.
1666
1667#define FOO(a, b) Bar((a) + 1, b)       // 'a' needs parentheses, whereas 'b' does not.
1668```
1669
1670### <a name="r6-2"></a>Rule 6.2 Place implementation statements of function-like macros that contain multiple statements in a `do-while(0)`.
1671
1672Macros do not have code blocks. When a macro is expanded at the call point, the expressions and variables defined in the macro are integrated into the calling code. As a result, variable name conflict and segmentation of macro statements may occur. Use `do-while(0)` to add a boundary to the macro so that the macro has an independent scope. In addition, a single statement can be formed by combining the macro with a semicolon (;) to avoid this problem.
1673
1674Incorrect example:
1675
1676```c
1677// Not Good
1678#define FOO(x) \
1679    (void)printf("arg is %d\n", (x)); \
1680    DoSomething((x));
1681```
1682
1683When the macro is called as shown in the following example code, the `for` loop only executes the first statement of the macro, and the next statement of the macro is executed only after the loop ends.
1684
1685```c
1686for (i = 1; i < 10; i++)
1687    FOO(i);
1688```
1689
1690To solve the preceding problem, use braces to enclose the statements defined by `FOO`.
1691
1692```c
1693#define FOO(x) { \
1694    (void)printf("arg is %d\n", (x)); \
1695    DoSomething((x)); \
1696}
1697```
1698
1699The brackets are not associated with semicolons (;). The semicolon following the braces is another statement.
1700In the following code example, the "suspended else' compilation error message is displayed.
1701
1702```c
1703if (condition)
1704    FOO(10);
1705else
1706    FOO(20);
1707```
1708
1709The correct format is to wrap the executed body using a `do-while(0)`, as shown in the following:
1710
1711```c
1712// Good
1713#define FOO(x) do { \
1714    (void)printf("arg is %d\n", (x)); \
1715    DoSomething((x)); \
1716} while (0)
1717```
1718
1719Exceptions:
1720
1721- Macros that contain 'break' or 'continue' statements can be treated as exceptions. Do use these macros carefully.
1722- An exception can be made when the macro contains an incomplete statement. For example, use a macro to encapsulate the conditional part of the `for` loop.
1723- An exception can be a non-multiple statement, or a single `if`, `for`, `while`, or `switch` statement.
1724
1725### <a name="r6-3"></a>Rule 6.3 Do not pass expressions with side effects to a function-like macro.
1726
1727Since macros are replaced by text, if a function-like macro uses the same macro parameter multiple times and transfers expressions with side effects as macro parameters, unexpected results may occur.
1728As shown in the following example, the macro `SQUARE` is normal, but the `a++` expression with side effects is passed to the macro. As a result, the value of `a` is different from the expected value after the `SQUARE` macro is executed.
1729
1730```c
1731#define SQUARE(a) ((a) * (a))
1732
1733int a = 5;
1734int b;
1735b = SQUARE(a++);    // Bad: 'a' is added twice.
1736```
1737
1738`SQUARE(a++)` is expanded to `((a++) * (a++))` the variable `a` is added twice, and its value is `7` instead of the expected `6`.
1739
1740The correct format is as follows:
1741
1742```c
1743b = SQUARE(a);
1744a++; // Result: a = 6, which is added only once.
1745```
1746
1747In addition, if the macro parameter contains a function call, the function may be called repeatedly after the macro is expanded.
1748If the function execution results are the same, it is a waste; if the results are different, the execution result may not meet the expected value.
1749
1750### <a name="a6-2"></a>Rec 6.2 Exercise caution when you use the statements such as `return`, `goto`, `continue`, and `break` in a function-like macro definition.
1751
1752Although process changing statements, such as `return`, `goto`, `continue`, and `break`, in a macro can simplify the code, they hide the real process, which hinders understanding and easily causes resource leakage.
1753
1754First, the macro encapsulation of the `return` statement can easily lead to excessive encapsulation and use.
1755As shown in the following code, the judgment of `status` is a part of the main process. After being encapsulated in macros, the purpose is not intuitive. The `RETURN_IF` macro is ignored, causing a confused understanding.
1756
1757```c
1758#define LOG_AND_RETURN_IF_FAIL(ret, fmt, ...) do { \
1759    if ((ret) != OK) {                             \
1760        (void)ErrLog(fmt, ##__VA_ARGS__);          \
1761        return (ret);                              \
1762    }                                              \
1763} while (0)
1764
1765#define RETURN_IF(cond, ret) do {                  \
1766    if (cond) {                                    \
1767        return (ret);                              \
1768    }                                              \
1769} while (0)
1770
1771ret = InitModuleA(a, b, &status);
1772LOG_AND_RETURN_IF_FAIL(ret, "Init module A failed!"); // OK
1773
1774RETURN_IF(status != READY, ERR_NOT_READY);  // Bad: The most important logic is not obvious.
1775
1776ret = InitModuleB(c);
1777LOG_AND_RETURN_IF_FAIL(ret, "Init module B failed!"); // OK
1778```
1779
1780Second, if `return` is encapsulated in a macro, it may also cause a memory leak. Example:
1781
1782```c
1783#define CHECK_PTR(ptr, ret) do { \
1784    if ((ptr) == NULL) { \
1785        return (ret); \
1786    } \
1787} while (0)
1788
1789...
1790
1791mem1 = MemAlloc(...);
1792CHECK_PTR(mem1, ERR_CODE_XXX);
1793
1794mem2 = MemAlloc(...);
1795CHECK_PTR(mem2, ERR_CODE_XXX);  // Wrong: Memory leak.
1796```
1797
1798If `mem2` fails to apply for memory, `CHECK_PTR` will return a message instead of releasing `mem1`.
1799Besides, the name of the `CHECK_PTR` macro is not good. The macro name only reflects the check action and does not specify the result. Readers can see that a failure is returned when the pointer is null only after viewing the macro implementation. It's not inherently obvious.
1800
1801In summary, it is not recommended to encapsulate process changing statements, such as `return`, `goto`, `continue`, and `break`, in macro definitions.
1802However, these macros can be used in special scenarios, such as return value judgment.
1803
1804Note: **Macro names must contain descriptive keywords if process changing statements, such as `return`, `goto`, `continue`, and `break`, are used.**
1805
1806### <a name="a6-3"></a>Rec 6.3 Include no more than 10 lines in a function-like macro (excluding blank lines and comments).
1807
1808A function-like macro is more difficult to debug and locate than a function, especially when the macro is too long.
1809Macro expansion will also lead to more compiled code. It is recommended that function-like macros contain no more than 10 lines.
1810
1811# <a name="c7"></a>7 Variables
1812
1813In C language coding, variables are the most important except for functions.
1814When using a variable, you should always follow the principle of "single responsibility".
1815By scope, variables can be classified into global variables and local variables.
1816
1817## <a name="c7-1"></a>Global Variables
1818
1819Do not use or avoid using global variables.
1820In program design, global variables are variables that are accessible to all scopes. Using unnecessary global variables is generally considered a bad habit.
1821
1822Disadvantages of global variables:
1823
1824- Destroys the independence and portability of a function. Functions can be dependent on global variables and increased coupling results.
1825- Reduces readability and maintainability. When multiple functions read and write to global variables, their values may not be determinate, which is unfavorable for comprehension and maintenance.
1826- In a concurrent programming environment, global variables will hinder reentry of functions. Additional synchronization protection must be added to ensure data security.
1827
1828If unavoidable, the read and write of global variables should be encapsulated in a centralized manner.
1829
1830### <a name="r7-1"></a>Rule 7.1 Do not use global variables as interfaces between modules.
1831
1832Global variables are for the internal implementation of modules and should not be exposed as interfaces.
1833Global variables should be as centralized as possible. If the data of this module needs to be disclosed to external modules, a function as an interface to this data should be provided.
1834
1835## <a name="c7-2"></a>Local Variables
1836
1837### <a name="r7-2"></a>Rule 7.2 Do not use uninitialized variables as rvalues.
1838
1839The variable here refers to a local dynamic variable, and also includes a memory block obtained on a memory heap.
1840Because their initial values are unpredictable, it is prohibited to use them directly as rvalues without effective initialization.
1841
1842```c
1843void Foo(...)
1844{
1845    int data;
1846    Bar(data);  // Bad: Uninitialized variables are used as rvalues.
1847    ...
1848}
1849```
1850
1851If there are different branches, ensure that all branches are initialized before being used as rvalues.
1852
1853```c
1854void Foo(...)
1855{
1856    int data;
1857    if (...) {
1858        data = 100;
1859    }
1860    Bar(data);  // Bad: This value is not initialized in some branches.
1861    ...
1862}
1863```
1864
1865Uninitialized rvalues can be found by generic static check tools.
1866For example, the PCLint tool reports a warning for the following two examples.
1867
1868> Warning 530: Symbol 'data' (line ...) not initialized Warning 644: Variable 'data' (line ...) may not have been initialized
1869
1870### <a name="r7-3"></a>Rule 7.3 Forbid invalid and redundant variable initialization.
1871
1872If the initial value is not determined before initialization is performed, it is not concise or secure and may cause problems that are more difficult to discover.
1873
1874Common redundant initialization:
1875
1876```c
1877int cnt = 0;    // Bad: Redundant initialization. It will be overwritten by later initialization.
1878...
1879cnt = GetXxxCnt();
1880...
1881```
1882
1883Variables with conditional values can be initialized to default values during definition.
1884
1885```c
1886char *buf = NULL;   // Good: NULL as the default value
1887if (condition) {
1888    buf = malloc(MEM_SIZE);
1889}
1890...
1891if (buf != NULL) {  // Check whether memory has been allocated.
1892    free(buf);
1893}
1894```
1895
1896Even worse, redundant clearing for arrays may affect the performance.
1897
1898```c
1899char buf[VERY_BIG_SIZE] = {0};
1900memset(buf, 0, sizeof(buf));    // Bad: Redundant clearing
1901```
1902
1903Invalid initialization, which hides a more severe problem:
1904
1905```c
1906void Foo(...)
1907{
1908    int data = 0;   // Bad: regular initialization
1909
1910    UseData(data);          // UseData should be placed after GetData.
1911    data = GetData(...);    // Get data.
1912    ...
1913}
1914```
1915
1916In the preceding code, if 0 is not assigned before initialization, the static check tool can help find the problem of "direct use without being initialized".
1917However, due to invalid initialization, the defect of placing "UseData" before "GetData" cannot be easily found.
1918
1919Therefore, simple code should be written to initialize variables or memory blocks as required.
1920
1921The C99 does not limit the definition position of local variables to before the first statement in a function. That is, a variable can now be defined close to a variable.
1922This concise approach not only limits the scope of the variable scope, but also solves the problem of how to initialize the variable when it is defined.
1923If this compilation environment is supported, you are advised to define local variables in this way.
1924
1925**Exceptions:**
1926**As 'Secure Coding Standard' required, pointers, resource variables, and boolean variables can be treated as exceptions of this rule.**
1927
1928### <a name="r7-4"></a>Rule 7.4 Do not use magic numbers.
1929
1930The so-called magic numbers are the numbers that are unintelligible and difficult to understand.
1931The magic number is not a concept that can be defined literally. It varies depending on context and service knowledge.
1932
1933For example, the number 12 varies in different contexts.
1934`type = 12;` is not intelligible, but `month = year * 12;` can be understood.
1935The number 0 is sometimes seen as a magic number. For example, the `status = 0;` cannot truly express any status information.
1936
1937Solution:
1938Comments can be added for numbers that are used only once.
1939For numbers that are used multiple times, macro or const variables must be defined and self-commented with symbolic naming.
1940
1941The following cases are forbidden:
1942The name is not used to explain the meaning of a number, for example, `#define ZERO 0`.
1943The value is limited by the name, for example, `#define XX_TIMER_INTERVAL_300MS 300`.
1944
1945# <a name="c8"></a>8 Programming Practice
1946
1947## <a name="c8-1"></a>Expressions
1948
1949### <a name="a8-1"></a>Rec 8.1 When comparing expressions, follow the principle that the left side tends to change and the right side tends to remain unchanged.
1950
1951When a variable is compared with a constant, placing the constant on the left, for example, `if (MAX == v)` does not read naturally, and `if (MAX > v)` is more difficult to understand.
1952The constant should be placed on the right according to the normal reading order and habit. The expression is written as follows:
1953
1954```c
1955if (v == MAX) ...
1956if (v < MAX) ...
1957```
1958
1959There are special cases: for example, the expression `if (MIN < v && v < MAX)` is used to check for a range. This first constant should be placed on the left.
1960
1961You do not need to worry about accidentally writing '==' as '=' because a compilation alarm will be generated for `if (v = MAX)` and an error will be reported by other static check tools. Use these tools to solve such writing errors and ensure that that code is readable.
1962
1963### <a name="r8-1"></a>Do not reference a variable again in an expression containing an increment (++) or decrement (--) operator.
1964
1965In an expression containing a variable increment or decrement operator, if the variable is referenced again, the result is not explicitly defined in the C standard, which may vary between compilers or different compiler versions.
1966For better portability, you should not make any assumptions about the operation sequence not defined in any standards.
1967
1968Note that this problem cannot be solved by using parentheses because it is not a problem of priority.
1969
1970Example:
1971
1972```c
1973x = b[i] + i++; // Bad: b[i] operation and i++, the order is not clear.
1974```
1975
1976The correct way is to add a separate line of increment or decrement:
1977
1978```c
1979x = b[i] + i;
1980i++;            // Good: Single line.
1981```
1982
1983Function parameter:
1984
1985```c
1986Func(i++, i);   // Bad: When passing the second parameter, it is not sure whether the increment operation has occurred.
1987```
1988
1989The correct way:
1990
1991```c
1992i++;            // Good: Single line.
1993x = Func(i, i);
1994```
1995
1996### <a name="a8-2"></a>Rec 8.2 Use parentheses to specify the sequence of expressions, instead of using the default priority.
1997
1998Parentheses can be used to better emphasize the purpose of used operators. This will prevent program errors due to the inconsistency between default priority and the intended design.
1999However, too many parentheses muddy the code, reducing readability. Use them moderately.
2000
2001Parentheses are recommended when expressions contain operators that are not commonly used and are confusing, such as bitwise operators.
2002
2003```c
2004c = (a & 0xFF) + b;     /* Parentheses are required while using bit operators. */
2005```
2006
2007## <a name="c8-2"></a>Statements
2008
2009### <a name="r8-2"></a>Rule 8.2 Provide a 'default' branch for the `switch` statement.
2010
2011In most cases, the 'default' branch exists in the switch statement to ensure that there is a default processing action when the case tag is missing.
2012
2013Exceptions:
2014If the switch condition variable is of the enum type and the case branches cover all values, then the default branch is redundant.
2015A modern compiler can check whether the case branch of some enumerated values is missing in the switch statement. A warning will be displayed.
2016
2017```c
2018enum Color {
2019    RED,
2020    BLUE
2021};
2022
2023// The switch condition variable is an enumerated value. Therefore, you do not need to add the 'default' processing branch.
2024switch (color) {
2025    case RED:
2026        DoRedThing();
2027        break;
2028    case BLUE:
2029        DoBlueThing();
2030        ...
2031        break;
2032}
2033```
2034
2035### <a name="a8-3"></a>Rec 8.3 Exercise caution when using the `goto` statement.
2036
2037The `goto` statement destroys the program. Avoid using it if possible. You can only jump to statements following the `goto` statement, and only within the one function.
2038
2039The `goto` statement is used to implement function return to a single point within a function.
2040If a function has a large number of identical logics that cannot be encapsulated, for example, repeated file execution, the processed part of code after the file operation failure (for example, closing the file handle and releasing memory that is dynamically applied for) is usually placed in the last part of the function body. And the goto statement is placed right before these. In this way, the code becomes clear and concise. It can also be encapsulated in functions or macros, but doing so makes code less straightforward.
2041
2042Example:
2043
2044```c
2045// Good: Use a goto statement to implement function return at a single point.
2046int SomeInitFunc(void)
2047{
2048    void *p1;
2049    void *p2 = NULL;
2050    void *p3 = NULL;
2051
2052    p1 = malloc(MEM_LEN);
2053    if (p1 == NULL) {
2054        goto EXIT;
2055    }
2056
2057    p2 = malloc(MEM_LEN);
2058    if (p2 == NULL) {
2059        goto EXIT;
2060    }
2061
2062    p3 = malloc(MEM_LEN);
2063    if (p3 == NULL) {
2064        goto EXIT;
2065    }
2066
2067    DoSomething(p1, p2, p3);
2068    return 0;   // OK.
2069
2070EXIT:
2071    if (p3 != NULL) {
2072        free(p3);
2073    }
2074    if (p2 != NULL) {
2075        free(p2);
2076    }
2077    if (p1 != NULL) {
2078        free(p1);
2079    }
2080    return -1;  // Failed!
2081}
2082```
2083
2084## <a name="c8-3"></a>Type Conversion
2085
2086### <a name="a8-4"></a>Rec 8.4 Minimize unnecessary type conversion and forced conversion.
2087
2088When the data type is forcibly changed, the meaning of the data and the value after conversion may change. If details are not considered, potential risks may be generated.
2089
2090In the following assignment, most compilers do not generate warnings, but the values are slightly changed.
2091
2092```c
2093char ch;
2094unsigned short int exam;
2095
2096ch = -1;
2097exam = ch; // Bad: Compilers does not generate any warnings. In this case, the value of exam is 0xFFFF.
2098```
2099