Write a good C language. A beautiful macro definition is very important. Using a macro definition can prevent errors, improve portability, readability, and convenience. The following lists some mature software commonly used macro definitions ......
1. prevent a header file from being repeatedly contained
# Ifndef comdef_h
# Define comdef_h
// Header file content
# Endif
2. redefine some types to prevent the differences in the number of bytes of the types caused by different platforms and compilers, so as to facilitate migration.
Typedef unsigned char Boolean;/* Boolean value type .*/
Typedef unsigned long int uint32;/* unsigned 32 bit value */
Typedef unsigned short uint16;/* unsigned 16 bit value */
Typedef unsigned char uint8;/* unsigned 8 bit value */
Typedef signed long int int32;/* signed 32 bit value */
Typedef signed short int16;/* signed 16 bit value */
Typedef signed Char int8;/* signed 8 bit value */
// The following is not recommended
Typedef unsigned char byte;/* unsigned 8 bit value type .*/
Typedef unsigned short word;/* unsinged 16 bit value type .*/
Typedef unsigned long DWORD;/* unsigned 32 bit value type .*/
Typedef unsigned char uint1;/* unsigned 8 bit value type .*/
Typedef unsigned short uint2;/* unsigned 16 bit value type .*/
Typedef unsigned long uint4;/* unsigned 32 bit value type .*/
Typedef signed Char int1;/* signed 8 bit value type .*/
Typedef signed short int2;/* signed 16 bit value type .*/
Typedef long int int4;/* signed 32 bit value type .*/
Typedef signed long sint31;/* signed 32 bit value */
Typedef signed short sint15;/* signed 16 bit value */
Typedef signed Char sint7;/* signed 8 bit value */
3. Get a byte or word on the specified address.
# Define mem_ B (x) (* (byte *) (x )))
# Define mem_w (x) (* (word *) (X )))
4. Calculate the maximum and minimum values.
# Define max (x, y) (x)> (y ))? (X): (y ))
# Define min (x, y) (x) <(y ))? (X): (y ))
5. Get the offset of a field in the struct (struct ).
# Define FPOs (type, field )/
/* Lint-e545 */(DWORD) & (type *) 0)-> Field)/* lint + e545 */
6. Obtain the number of bytes occupied by the field in the struct.
# Define fsiz (type, field) sizeof (type *) 0)-> field)
7. convert two bytes into a word in LSB format
# Define flipw (Ray) (Word) (Ray) [0]) * 256) + (Ray) [1])
8. convert a word into two bytes in LSB format.
# Define flopw (Ray, Val )/
(Ray) [0] = (VAL)/256 );/
(Ray) [1] = (VAL) & 0xff)
9. Get the address of a variable (word width)
# Define B _ptr (VAR) (byte *) (void *) & (VAR ))
# Define w_ptr (VAR) (word *) (void *) & (VAR ))
10 to obtain the high and low bytes of a word.
# Define word_lo (XXX) (byte) (Word) (XXX) & 255 ))
# Define word_hi (XXX) (byte) (Word) (XXX)> 8 ))
11. Return a multiple of 8 nearest to X.
# Define rnd8 (x) + 7)/8) * 8)
12. convert a letter into uppercase letters.
# Define upcase (C) (c)> = 'A' & (c) <= 'Z ')? (C)-0x20): (c ))
13. determines whether the character is a decimal number.
# Define decchk (C) (c)> = '0' & (c) <= '9 ')
14. determines whether the character is a hexadecimal number.
# Define hexchk (C) (c)> = '0' & (c) <= '9') |/
(C)> = 'A' & (c) <= 'F') |/
(C)> = 'A' & (c) <= 'F '))
15. A method to prevent overflow
# Define inc_sat (VAL) (val = (VAL) + 1> (VAL ))? (VAL) + 1: (VAL ))
16. returns the number of array elements.
# Define arr_size (A) (sizeof (a)/sizeof (A [0])
17. Return the value mod_by_power_of_two (x, n) = x % (2 ^ N) at the end of N)
# Define mod_by_power_of_two (Val, mod_by )/
(DWORD) (VAL) & (DWORD) (mod_by)-1 ))
18. For the structure of Io space ing in the bucket, Input/Output Processing
# Define Indium (port) (* (volatile byte *) (port )))
# Define inpw (port) (* (volatile word *) (port )))
# Define inpdw (port) (* (volatile DWORD *) (port )))
# Define outp (port, Val) (* (volatile byte *) (port) = (byte) (VAL )))
# Define outpw (port, Val) (* (volatile word *) (port) = (Word) (VAL )))
# Define outpdw (port, Val) (* (volatile DWORD *) (port) = (DWORD) (VAL )))
[Add]
19. Use some macro tracking for debugging
The a n s I Standard specifies five predefined macro names. They are:
_ L I n e _
_ F I L E _
_ D a t e _
_ T I m e _
_ S t d c _
If compilation is not standard, only a few of the above macro names are supported or not supported at all. Remember to compile the program
Other predefined macro names may also be provided.
The _ L I n e _ and _ f I l e _ macro commands have been discussed in the section about # l I n e. The remaining macro names are discussed here.
The _ d at E _ macro command contains a string in the form of month, day, or year, which indicates the date when the source file was translated to the code.
The time when the source code is translated to the target code is included in _ t I m e _ as a string. String format: minute: second.
If the implementation is standard, the macro _ s t d c _ contains the decimal constant 1. If it contains any other number, the implementation is
Non-standard.
You can define macros, for example:
When _ debug is defined, the output data and the row of the file
# Ifdef _ debug
# Define debugmsg (MSG, date) printf (MSG); printf ("% d", date, _ line _, _ file _)
# Else
# Define debugmsg (MSG, date)
# Endif
20. macro definition to prevent usage from being incorrect
Enclosed in parentheses.
Example: # define add (a, B) (a + B)
Use the do {} while (0) statement to include multiple statements to prevent errors.
Example: # difne do (A, B) A + B ;/
A ++;
Application Time: If (....)
Do (a, B); // generate an error
Else
Solution: # difne do (a, B) do {A + B ;/
A ++;} while (0)
Usage of "#" and "#" in macro
I. general usage
We use # to convert the macro parameter into a string, and # to combine the two macro parameters.
Usage:
# Include <cstdio>
# Include <climits>
Using namespace STD;
# Define STR (s) # s
# Define cons (a, B) int (A ## e ## B)
Int main ()
{
Printf (STR (vck); // output string "vck"
Printf ("% d/N", cons (2000); // 2e3 output:
Return 0;
}
2. When the macro parameter is another macro
It should be noted that all macro parameters that use '#' or '#' in macro definition will not be expanded.
1. Non-'#' and '#'
# Define tow (2)
# Define MUL (a, B) (a * B)
Printf ("% d * % d = % d/N", tow, tow, MUL (tow, tow ));
The Macros in this line will be expanded:
Printf ("% d * % d = % d/N", (2), (2), (2) * (2 )));
The tow parameter in Mul is expanded to (2 ).
2. When '#' or '#' is available
# Define a (2)
# Define STR (s) # s
# Define cons (a, B) int (A ## e ## B)
Printf ("int MAX: % s/n", STR (int_max); // int_max # include <climits>
This row is expanded:
Printf ("int MAX: % s/n", "int_max ");
Printf ("% s/n", cons (A, A); // compile Error
This line is:
Printf ("% s/n", INT (AEA ));
Int_max and a will not be expanded. However, the solution to this problem is simple. add another layer of intermediate conversion macro.
The purpose of adding this macro layer is to expand all macro parameters in this layer, so that the macro (_ Str) in the conversion macro can get the correct macro parameters.
# Define a (2)
# DEFINE _ STR (s) # s
# Define STR (s) _ STR (s) // convert macro
# DEFINE _ cons (a, B) int (A ## e ## B)
# Define cons (a, B) _ cons (a, B) // convert a macro
Printf ("int MAX: % s/n", STR (int_max); // The maximum value of int_max, int type, is a variable # include <climits>
Output: int MAX: 0x7fffffff
STR (int_max) --> _ STR (0x7fffffff) and then convert it to a string;
Printf ("% d/N", cons (A, ));
Output: 200
Cons (a, a) --> _ cons (2), (2) --> int (2) E (2 ))
Iii. Special Application Cases of '#' and '#'
1. Merge anonymous variable names
# Define ___ anonymous1 (type, VAR, line) type var # Line
# DEFINE _ anonymous0 (type, line) ___ anonymous1 (type, _ anonymous, line)
# Define anonymous (type) _ anonymous0 (type, _ line __)
For example, anonymous (static INT); that is, static int _ anonymous70; 70 indicates the row number;
First layer: anonymous (static INT); --> _ anonymous0 (static int, _ line __);
Layer 2: --> ___ anonymous1 (static int, _ anonymous, 70 );
Layer 3: --> static int _ anonymous70;
That is, the macro of the current layer can only be unlocked at each time, so _ line _ can be unlocked at the second layer;
2. fill Structure
# Define fill (a) {A, #}
Enum IDD {open, close };
Typedef struct MSG {
Idd id;
Const char * MSG;
} MSG;
MSG _ MSG [] = {fill (open), fill (close )};
Equivalent:
MSG _ MSG [] = {open, "open "},
{Close, "close "}};
3. Record File Name
# DEFINE _ get_file_name (f) # F
# Define get_file_name (f) _ get_file_name (f)
Static char file_name [] = get_file_name (_ file __);
4. Obtain the buffer size of the string corresponding to the value type.
# DEFINE _ type_buf_size (type) sizeof # type
# Define type_buf_size (type) _ type_buf_size (type)
Char Buf [type_buf_size (int_max)];
--> Char Buf [_ type_buf_size (0x7fffffff)];
--> Char Buf [sizeof "0x7fffffff"];
This is equivalent:
Char Buf [11];