A single line definition of a macro
#define A (x) t_# #x
#define B (x) #@x
#define C (x) #x
We assume: x=1, then there are:
A (1)------〉t_1
B (1)------' 1 '
C (1)------"1"
. How to define macros, cancel macros
Defining macros
#define [macroname] [Macrovalue]
Cancel macros
#undef [macroname]
Common macros
#define PI (3.1415926)
Macros with parameters
#define MAX (A,b) ((a) > (b)? (a), (b))
The key is very easy to produce errors, including machine and human understanding of the differences and so on.
Write good C language, beautiful macro definition is very important, the use of macro definitions can prevent errors, improve portability, readability, convenience and so on. The following is a list of commonly used macro definitions in mature software ...
1, prevent a header file from being repeatedly included
#ifndef Comdef_h
#define Comdef_h
Header file Contents
#endif
2, redefine some types to prevent the different types of platform and compiler, resulting in a difference in the number of bytes, easy to migrate.
typedef unsigned char Boolean; /* Boolean value type. */
typedef unsigned long int uint32; /* Unsigned bit value * *
typedef unsigned short uint16; /* Unsigned bit value */
typedef unsigned char uint8; /* Unsigned 8 bit value */
typedef signed Long int int32; /* Signed bit value * *
typedef signed short Int16; /* Signed bit value */
typedef signed CHAR int8; /* Signed 8 bit value */
3, to find the maximum and minimum value
#define MAX (x, y) ((x) > (y))? (x): (y))
#define MIN (x, Y) (((x) < (y))? (x): (y))
4, get a byte or word on the specified address
#define MEM_B (x) (* ((BYTE *) (x))
#define MEM_W (x) (* (Word *) (x))
5, to get the number of bytes occupied by field in a struct
#define FSIZ (type, field) sizeof ((type *) 0)->field)
6, to get the offset of a field in the structure body (struct)
#define FPOS (Type, field)/*lint-e545 */((DWORD) & ((type *) 0)-> field)/*lint +e545 * *
7, convert two bytes to a word in the LSB format
#define FLIPW (((Word) (Ray) [0]) * 256) + (ray) [1])
8, converts a word to two bytes in 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 *) (void *) & (Var))
#define W_PTR (VAR) (word *) (void *) & (Var))
10, get a high and low byte of a word
#define WORD_LO (XXX) ((byte) (WORD) (XXX) & 255)
#define WORD_HI (XXX) ((byte) (WORD) (XXX) >> 8)
11, returns a multiple of the nearest 8, which is larger than X
#define RND8 (x) (((x) + 7)/8) * 8)
12, converts a letter to uppercase
#define UPCASE (c) ((c) >= ' A ' && (c) <= ' Z ')? ((c)-0x20): (c))
13, to determine whether the character is a number of 16 values
#define HEXCHK (c) (((c) >= ' 0 ' && (c) <= ' 9 ') | | \
(c) >= ' A ' && (c) <= ' F ') | | \
((c) >= ' A ' && (c) <= ' F '))
14, to determine whether the character is a number of 10 values
#define DECCHK (c) ((c) >= ' 0 ' && (c) <= ' 9 ')
15. One way to prevent overflow
#define INC_SAT (val) (val = ((val) +1 > (val))? (val) +1: (val))
16, returns the number of elements in the array
#define ARR_SIZE (a) (sizeof ((a))/sizeof ((a[0)))
17, returns an unsigned number N-tailed value Mod_by_power_of_two (x,n) =x% (2^n)
#define Mod_by_power_of_two (val, mod_by) \
((DWORD) (VAL) & (DWORD) ((mod_by)-1))
18, for IO space mapping in the structure of storage space, input output processing
#define &NBSP;INP (port) ((volatile byte *) (port))
#define &NBSP;INPW (port) ((volatile word *) (port))
#define INPDW (port) (* (volatile dword *) (port))
# DEFINE&NBSP;OUTP (Port, val) (* (volatile byte *) (port) = ( BYTE) (val))
#define &NBSP;OUTPW (port, val) (volatile word *) (port) = ((word) (val))
#define &NBSP;OUTPDW (port, val) (* ( volatile dword *) (port) = ((DWORD) (val)))
19, using some macro-tracing debugging
The A n s i standard describes 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, You may support only a few of the macro names above or do not support them at all. Remember that the compiler
may also provide other predefined macro names.
_ l i n e _ and _&NBSP;F&NBSP;I&NBSP;L&NBSP;E&NBSP;_ macro directives in the relevant # l i n discussed in the e section, the remaining macro names are discussed here. The
_ d at e _ macro directive contains a string of month/day/year, indicating the date when the source file was translated to code. The time the
Source code is translated into the target code is included in the _ t i m e _ as a string. String form last: minutes: seconds.
If the implementation is standard, the macro _ s t d c _ contains a decimal constant of 1. If it contains any other number, the implementation is
non-standard.
You can define macros, such as:
when _DEBUG is defined, the output data information and the row where the file is located
#ifdef _debug
#define &NBSP;DEBUGMSG (msg,date) printf (msg);p rintf ("%d%d%d", Date,_line_,_file_)
#else
#define Debugmsg (msg,date)
#endif
20, macro definition to prevent use is an error
Included with parentheses.
Example: #define ADD (A,B) (a+b)
Use Do{}while (0) statement to contain multiple statements to prevent errors
For example: #difne do (a,b) a+b;\
a++;
When applied: if (...)
Do (A,B); Generate an error
Else
Workaround: #difne Do (a,b) do{a+b;\
a++;} while (0)
Usage of "#" and "# #" in macros
I. GENERAL usage
We use # To change the macro parameter to a string, with # #把两个宏参数贴合在一起.
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", CONS (2,3)); 2E3 Output: 2000
return 0;
}
Second, when the macro parameter is another macro
The local macro parameters that need to be noted for ' # ' or ' # # ' in the macro definition are not expanded.
1, not ' # ' and ' # # ' situation
#define TOW (2)
#define MUL (A,b) (a*b)
printf ("%d*%d=%d", TOW, TOW, MUL (Tow,tow));
This line of macros is expanded to:
printf ("%d*%d=%d", (2), (2), ((2) * (2)));
The parameter tow in the MUL will be expanded to (2).
2, when there is ' # ' or ' # # '
#define A (2)
#define STR (s) #s
#define CONS (a,b) int (a# #e # #b)
printf ("Int max:%s", STR (Int_max)); Int_max #include <climits>
This guild is expanded to:
printf ("Int max:%s", "Int_max");
printf ("%s", CONS (A, a)); Compile error
This line is:
printf ("%s", int (AeA));
Int_max and A are not going to be expanded, but the solution to this problem is simple. Add one more layer of intermediate conversion macros.
The idea of adding this macro is to expand all of the macro parameters in this layer, and then the macro in the conversion macro (_STR) can get the correct macro parameters.
#define A (2)
#define _STR (s) #s
#define STR (s) _str (s)//Convert macros
#define _CONS (a,b) int (a# #e # #b)
#define CONS (a,b) _cons (a,b)//Convert macros
printf ("Int max:%s", STR (Int_max)); The maximum value of the Int_max,int type for a variable #include <climits>
Output is: int max:0x7fffffff
STR (Int_max)--> _str (0x7fffffff) is then converted to a string;
printf ("%d", CONS (A, a));
Output is: 200CONS (A, a)--> _cons ((2), (2))--> Int ((2) E (2))
Third, ' # ' and ' # # ' Some of the application of special cases
1. Merging 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__)
Example: ANONYMOUS (static int); namely: static int _anonymous70; 70 indicates the line number;
First layer: ANONYMOUS (static int); --> __anonymous0 (static int, __line__);
Second layer:--> ___anonymous1 (static int, _anonymous, 70);
Third layer:--> static int _anonymous70;
That is, each time only the current layer of the macro can be solved, so __line__ in the second layer can be untied;
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:
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 numeric type corresponding to the string buffer size
#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 to:
Char buf[11];