Current location - Plastic Surgery and Aesthetics Network - Plastic surgery and beauty - The usage of static in C5 1
The usage of static in C5 1
choose

Written by non-programmers

There will always be bugs in the code, and there is no best but better in this respect. Efficient is what programmers must do, and error-free is the pursuit of programmers all their lives. Reuse, divide and conquer and compromise are the basic ideas of code philosophy. Modularity and object-oriented are the methods to realize efficient and error-free code. Efficient error-free code requires repeated thinking and practice.

1.2. 1 naming convention

The command specification basically adopts Hungarian nomenclature recommended by Microsoft, which is slightly simplified.

1. constant

Constants consist of uppercase letters and numbers separated by underscores, such as CPU_805 1.

2. Variable

Variables start with lowercase letters (variable types) and are separated by uppercase letters. You can add variable domain prefixes (variable active domain prefixes are separated by underscores). Such as: v_nAcVolMin (minimum AC voltage).

The prefix of variable fields is shown in the following table.

Local variables, if the meaning of the variable name is obvious, are not prefixed to avoid triviality. For example, int variables I, J, K for loop; Floating-point three-dimensional coordinates (x, y, z), etc.

3. Function names generally start with capital letters and are separated by capital letters, such as SetSystemPara. Function naming adopts verb-object form. If the function is at the bottom, consider using all lowercase and underlined words. For example, the underlying graphic functions: pixel, lineto and read keyboard function get_key, etc.

4. Symbol names should be universal or have specific meanings and readable. Especially for global variables, the meaning of static variables must be clear. Some keywords in C++ cannot be used as symbolic names, such as class, new, friend, etc. The length of symbol name is less than 3 1, which is consistent with ANSI C. Naming can only consist of 26 letters, 10 numbers and underscore "_". Do not use symbols such as "$" and "@". The underscore' _' should be eye-catching, not at the head and tail of the symbol, only in the middle of the symbol, and should not appear twice in a row.

5. There are few meaningless numbers in the program, so try to replace the constants with macros.

1.2.2 using assertions

Programs are generally divided into debug version and release version. The debug version is used for internal debugging, and the release version is released to users.

Assert is a macro that only works in the debug version. It is used to check what should not happen. The following is a memory copy program. During operation, if the parameter of assert is false, the program will stop (usually a prompt dialog box will appear to explain where assert was triggered).

//Copy non-overlapping memory blocks

void memcpy(void *pvTo,void *pvFrom,size_t size)

{

void * pbTo =(byte *)pvTo;

void * Pb from =(byte *)PV from;

Assertion (pvTo! = NULL & amp& amppvFrom! = NULL);

while(size---gt; 0 )

* pbto++ = * Pb from++;

Return (pvto);

}

Assert is not a hastily pieced macro. Assert should not have any side effects in order not to cause the difference between the debug version and the release version of the program. So assert is not a function, but a macro. Programmers can regard assert as a harmless test method, which can be used safely in any system state.

Here are some principles for using assertions:

1) uses assertions to catch illegal situations that should not happen. Don't confuse the difference between illegal situation and wrong situation, the latter is inevitable and must be dealt with.

2) Use assertions to confirm the parameters of the function.

3) When writing a function, double-check and ask yourself, "What assumptions should I make?" Once you have determined your assumptions, you should check them with assertions.

4) General textbooks encourage programmers to design error-proof programs, but remember that this programming style will hide mistakes. In error-proof programming, if something "impossible" does happen, you should use assertions to sound an alarm.

1.2.3 optimization/efficiency

Rule 1: Apply volatile definitions to global variables used in interrupt functions/threads and external functions. For example:

Variable integer tick point;

Voidtimer (void) interrupt 1// interrupt handler

{

Didi++

}

Invalid Wait (Intermediate Interval)

{

tick = 0;

While (tick & lt interval);

}

If volatile is not used, since the while loop is an empty loop, the compiler will optimize the loop to an empty operation after optimization (the compiler does not know that this variable is used in the interrupt)! This is obviously wrong.

Rule 2: Don't write too complicated statements. Compact C++/C code will not get efficient machine code, but will reduce the understandability of the program and increase the probability of program error.

Rule 3: application principles in variable type programming: try to use small types (if possible, try not to use "Float") and unsigned unsigned types, because symbolic operation takes a long time; At the same time, the return value of the function is unsigned, which brings another benefit: it avoids hidden errors caused by different types of data comparison operations.

1.2.4 others

Rule 1: Don't write a function with multiple functions, and don't confuse the normal value with the error flag in the return value of the function.

Rule 2: Do not program BOOL values TRUE and FALSE to correspond to 1 and 0. Most programming languages define FALSE as 0, and any value except 0 is TRUE. Visual C++ defines TRUE as 1, and Visual Basic defines TRUE as-1. For example:

Boolean sign;

If(flag) {// Do sth}//Correct usage

If(flag = = true){//something }/ dangerous usage

If (flag = =1) {//dosomething}/dangerous usage

If (! Flag) {// Do sth}//Correct usage

Unreasonable usage of if (flag = = false) {//dosomething}//

Unreasonable usage of if (flag = = 0) {//doing something}//

Rule 3: Be careful not to write "= =" as "=", the compiler will not find this error automatically.

Rule 4: It is recommended that the return value of the unified function be an unsigned integer, where 0 means there is no error and others mean the error type.

1.3 modular c programming

Although C language does not have the object-oriented component of C++, it should still absorb the object-oriented idea and adopt the modular programming idea. Object-oriented thought and object-oriented language are two concepts. Non-object-oriented languages can still complete object-oriented programming. Think about the birth of C++!

There is no reason for C++ to be arrogant and biased against C. Not every occasion, C++ method is a good medicine to solve problems, such as facing the dual needs of embedded system efficiency and space. Note that we are talking about methods, not compilers.

The primary problem of C in software development is the lack of control (encapsulation) of data access. C programmers happily use a large number of global variables in the form of extern to exchange data between modules. "How convenient!" Programmers are happy to pass it on to the next programmer. So many variables appear in many modules, and the cutting is still chaotic, until one day I finally found it difficult to find a "person". A thing tastes good, smart people taste it and improve it, while stupid people only die.

There is no savior in this world. Programmers and founders of C have long thought about it. I believe there is spring among wild lilies. Let's take a look at how C language realizes the modular programming method, which has the encapsulation and polymorphism of OO characteristics to a certain extent.

Before elaborating, the concepts of lifetime and visibility need to be clarified. Lifetime refers to the life cycle of a variable in memory, and visibility refers to whether the variable is available at the current location. The two are closely related, but they cannot be confused. It is not surprising that a person's existence but invisibility can only be explained as God or soul, and that a variable exists but invisibility. Modularization method takes advantage of the special survivability and visibility of static functions and static variables.

Finally, it needs to be clear that the module here is based on a. c file.

Rule 1: Use function naming rules and static functions.

Internal functions in a module that are not called by other modules adopt the following naming rules: use all lowercase and underlined words. For example, the underlying graphic functions: pixel, lineto and read keyboard function get_key, etc. These functions should be defined as static static functions, so that when other modules call these functions incorrectly (such as BC compiler), the compiler can give an error. (Note: Some compilers cannot report errors, but it is recommended to do so for the sake of consistent code style and clear function hierarchy).

Rule 2: Use static variables.

Global variables in a module that cannot be read or written by other modules should be declared statically so that when other modules read or write these variables incorrectly, the compiler can give a warning (C5 1 compiler) or an error (BC compiler).

Rule 3: Introduce the concepts of OO interface and pointer passing parameters.

The data interfaces (i.e. functions) between modules should be fully considered in advance, which interfaces are needed and which data need to be operated through the interfaces, and the interfaces should be kept unchanged as far as possible.

The data exchange between modules is completed through interfaces as far as possible by passing parameters through functions. In order to ensure the high efficiency of the program and reduce the stack space, a large number of parameters (such as structures) should be passed through addresses, and pointers should be returned as function parameters or functions to avoid global variables appearing in the form of extern. Please note that global variables in the form of extern are allowed and necessary.

The increased overhead of passing pointer parameters is mainly the data space of pointers and local pointers (embedded systems (such as C5 1) often put function parameters in the stack of external RAM due to the limited stack space), and the increased code overhead is only the call of functions, which brings a good modular structure. Using interface functions will greatly save code space than using global variables directly in many places in the code.

Things that need attention always have two sides, and water can carry a boat and overturn it. If variables that need frequent access are still passed through the interface, the overhead of function call is huge. At this point, we should consider still using the extern global variable.

The following shows two C modules for exchanging data:

//module 1. C

one struct * void GetOneStruct(void); //acquisition module 1 data interface

void SetOneStruct(one struct * pone struct); //write module 1 data interface

Structure-structure

{

int m? _ imember

//……

} t 1; //module 1

//t 1 initialization code .....

one struct * void GetOneStruct(void)

{

one struct * pt 1; //Only one local variable is defined.

t 1 . I member = 15;

pt 1 = & amp; t 1;

Return pt1;

}

void SetOneStruct(one struct * pone struct)

{

t 1 . I member = pone struct-& gt; imember

//…….

}

//Module 2. C

void operate construct(void); //Module 2 operates the data of module 1 through the interface provided by module 1.

one struct * void GetOneStruct(void);

void SetOneStruct(one struct * pone struct);

void operate construct(void)

{

OneStruct * pt2// Only one local variable is defined.

pt2 = getone struct(); //Read data

SetOneStruct(pt2); //Overwrite data

}

Using interfaces to access data can avoid some errors, because the return value of functions can only be correct, while global variables are not.

For example, cOneChar = = 4;; May be mistaken for cOneChar = 4;;

Rule 4: Finite encapsulation and polymorphism

Don't forget that the class of C++ comes from the struct of C, and the virtual function mechanism of C++ is essentially a function pointer. In order to encapsulate data and methods together and improve code reusability, for example, for some hardware-related data structures, it is suggested that the function accessing the data structure is defined as the function pointer inside the structure. In this way, when the hardware changes, it is necessary to rewrite the function that accesses the hardware. As long as the rewritten function address is assigned to the function pointer, the high-level code does not need to move at all because the function pointer is used, and the code reuse is realized. Moreover, function pointers can be passed to high-level codes by passing parameters or global variables, which is more convenient. For example:

Structure-structure

{

int m? _ imember

int (*func)(int,int);

//……

} t2