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