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