C language macro definition skills (common macro definition)
Write a good C language, a beautiful macro definition is important, using macro definitions can prevent errors, improve portability, readability, convenience, and more. The following is listed in some mature software commonly used macro definitions.
1. Prevent a header file from being repeated
#ifndef comdef_h
#DEFINE COMDEF_H
// header file content
#ENDIF
2, redefine some types to prevent different types of bytes due to various platforms and compilers, and convenient portation.
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 Int32; / * Signed 32 Bit Value * /
Typedef Signed Short Int16; / * Signed 16 Bit Value * /
Typedef Signed Char Int8; / * Signed 8 Bit Value * /
// Not recommended below
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 rt4; / * 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 one byte or word on the specified address
#define mem_b (x) (* (Byte *) (x)))))))))
#define MEM_W (X) (* (Word *))))))
4, seek maximum and minimum
#define max (x, y) ((x)> (y))? (x): (y))
#define min (x, y) ((x) <(y))? (x): (y))
5, get an offset in a field in the structure (STRUCT)
#define fpos (Type, Field) \
/ * LINT -E545 * / (DWORD) & ((TYPE *) 0) -> Field) / * Lint E545 * /
6. Get the number of bytes occupied by Field in a structure
#define fsiz (Type, Field) SIZEOF ((Type *) 0) -> Field)
7. Convert two bytes to a word according to the LSB format
#define flipw (ray) ((Word) (r) [0]) * 256) (ray) [1])
8, convert a word into two bytes according to the 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 *) & (var))
#define w_ptr (var) (word *) & (var))
10, get the high and low bytes of words
#define word_lo (xxx) ((Byte) ((Word) & 255)))
#define Word_hi (XXX) ((Byte) ((Word) >> 8))
11. Returns a multiple of the closest 8 than X
#DEFINE RND8 (X) (((x) 7) / 8) * 8)
12, convert a letter to uppercase
#define Upcase (((c)> = 'a' && (c) <= 'z')? ((c) - 0x20): (c))
13. Decision characters are not 10% of values
#define Decchk (C) ((c)> = '0' && (c) <= '9')
14. Decision character is not a 16-input number
#define hexchk (((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, the number of returns to array elements
#define arr_size (a) (SIZEOF ((a)) / sizeof ((a [0]))))
17. Returns a value mod_by_power_of_two (x, n) = x% (2 ^ n)
#define mod_by_power_of_two (val, mod_by) \
((DWORD) & (DWORD) ((MOD_BY) -1)))
18. For the structure of the IO space mapped in the storage space, input and output processing
#define INP (port) (* (Volatile Byte *) (port))))
#define INPW (Port) (((Volatile Word *) (port)))
#define INPDW (Port) ((Volatile Dword *) (Port))))
#define outp (port, val) (* (Volatile Byte *) (Port)) = ((Byte)))))
#define outpw (port, val) ((Volatile Word *) (Port)) = ((Word))))
#define outpdw (port, val) (* ((volatile dword *) = ((DWORD) (VAL))))
19. Use some macro tracking debugging, A N s I standard illustrates five predefined macro names, they are:
l _Line_
l _file_
l _date_
l _Time_
l _STDC_
If compiled is not standard, you may only support several of the above macro names, or don't support it. Remember the compiler
Perhaps other predefined macro names are also available.
_ Line _ and _ file _ macro is discussed in the section of # line, here is discussed here.
_DATE _ Macro contains a string in the form of month / day / year, indicating the date when the source file is translated to the code. The source code is translated into the target code as a string being included in _Time_. String form is: points: seconds. If the implementation is a standard, the macro _STDC_ contains decimal constant 1. If it contains any other number, it is true to be non-standard.
You can define macros, for example:
When defining _debug, output data information and files are located
#ifdef _Debug
#define debugmsg (msg, date) Printf (MSG); Printf ("% D% D% D", Date, _Line _, _ file_)
#ELSE
#define debugmsg (MSG, DATE)
#ENDIF
20, macro definition prevention is wrong
Use parentheses.
For example: #define add (a, b) (A B)
Use the do {} while (0) statement containing multi-statement prevention errors
For example: #difne do (a, b) A B; \
A ;
Application: if (....)
Do (a, b); // Generate errors
Else
Solution: #difne do (a, b) do {a b; \
A ;} while (0)
Usage of "#" and "##" in macro
First, general usage
We use # to turn the macro parameters to a string, and bring two macro parameters together with ##.
usage:
#I nclude
#I nclude
Using namespace std;
#define str (s) #S
#define conce (a, b) INT (a ## e ## b)
int main ()
{
Printf (str (vck)); // Output string "VCK"
Printf ("% D \ N", CONS (2, 3)); // 2E3 output: 2000
Return 0;
}
Second, when the macro parameter is another macro
It should be noted that the place macro parameters of useful '#' or '##' in the macro definition will not be expanded.
1, not '#' and '##'
#define Tow (2) #define Mul (A, B) (A * B)
Printf ("% D *% D =% D \ N", Tow, Tow, Mul (Tow, Tow, Tow);
The macro of this line is deployed:
Printf ("% D *% D =% D \ N", (2), (2), ((2) * (2)));
The parameter TOW in MUL will be expanded (2).
2, when there is '#' or '##'
#define a (2)
#define str (s) #S
#define conce (a, b) INT (a ## e ## b)
Printf ("int_max); // int_max #i nclude
This line will be 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 unfolded, but the method to solve this problem is simple. Additional intermediate conversion macro.
Plus this macro intention is to expand all the parameters of all macros, then the macro (_STR) in the macro (_STR) can get the correct macro parameter.
#define a (2)
#define _str (s) #S
#define str (s) _STR (s) // conversion macro
#define _cons (a, b) int (a ## e ## b)
#define conce (a, b) _Cons (a, b) // conversion macro
Printf ("int_max); // int_max, INT type maximum, for a variable #i nclude
Output is: int MAX: 0x7fffffffff
Str (int_max) -> _str (0x7ffffff) and then convert to strings;
Printf ("% D \ N", CONS (A, A));
Output is: 200
CONS (A, A) - >_Cons ((2), (2)) -> INT ((2) E (2))
Some application special cases of the three, '#' and '##'
1, combined anonymous variable name
#define ___ anonymous1 (Type, Var, Line) Type Var ## line
#define __anonymous0 (Type, Line) ___ Anonymous1 (Type, _Anonymous, Line)
#define Anonymous (Type) __anonymous0 (Type, __LINE__)
Example: Anonymous (static int); ie: static int _anonymous70; 70 means the line number;
First layer: anonymous (static int); -> __ANonymous0 (static int, __line__);
Layer 2: -> ___ anonymous1 (static int, _onymous, 70);
Layer 3: -> static int _anonymous70;
That is, only the macro of the current layer can be unnaped each time, so __line__ can be unsaled at the second layer; 2, filling structure
#define fill (a) {a, #a}
Enum IDD {open, close};
Typedef struct msg {
IDD ID;
Const char * msg;
} Msg;
MSG_MSG [] = {Fill (Open), Fill (Close)};
Equivalent to:
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, get a string buffer size corresponding to a numeric type
#define _type_buf_size (type) Sizeof #Type
#define type_buf_size (type) _type_buf_size (Type)
Char buf [type_buf_size];
-> char buf [_type_buf_size];
-> Char BUF [SizeOf "0x7ffffff"];
Here is equivalent to:
Char BUF [11];