Some of the C language deserve to be defined as the beautiful macro definition of the common C language header library

Original text connection: https://mp.weixin.qq.com/s/OICAfQgMKWfBLuZbp2gCBw

Writing C language well, beautiful macro definition is very important. Using macro definition can prevent errors, improve portability, readability, convenience and so on. Here are some macro definitions commonly used in mature software.

1. Prevent a header file from being included repeatedly

1#ifndef COMDEF_H
2#define COMDEF_H
3//Header file content
4#endif

2. Redefine some types to prevent the difference of type bytes due to different platforms and compilers, so as to facilitate transplantation.

1typedef unsigned char boolean; /* Boolean value type. */
2typedef unsigned long int uint32; /* Unsigned 32 bit value */
3typedef unsigned short uint16; /* Unsigned 16 bit value */
4typedef unsigned char uint8; /* Unsigned 8 bit value */
5typedef signed long int int32; /* Signed 32 bit value */
6typedef signed short int16; /* Signed 16 bit value */
7typedef signed char int8; /* Signed 8 bit value */

The following is not recommended

 1typedef unsigned char byte; /* Unsigned 8 bit value type. */
 2typedef unsigned short word; /* Unsinged 16 bit value type. */
 3typedef unsigned long dword; /* Unsigned 32 bit value type. */
 4typedef unsigned char uint1; /* Unsigned 8 bit value type. */
 5typedef unsigned short uint2; /* Unsigned 16 bit value type. */
 6typedef unsigned long uint4; /* Unsigned 32 bit value type. */
 7typedef signed char int1; /* Signed 8 bit value type. */
 8typedef signed short int2; /* Signed 16 bit value type. */
 9typedef long int int4; /* Signed 32 bit value type. */
10typedef signed long sint31; /* Signed 32 bit value */
11typedef signed short sint15; /* Signed 16 bit value */
12typedef signed char sint7; /* Signed 8 bit value */

3. Get a byte or word on the specified address

1#define MEM_B( x ) ( *( (byte *) (x) ) )
2#define MEM_W( x ) ( *( (word *) (x) ) )

4. Find the maximum and minimum values

1#define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
2#define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )

5. Get the offset of a field in the structure

1#define FPOS( type, field ) \
2/*lint -e545 */ ( (dword) &(( type *) 0)-> field ) /*lint +e545 */

6. Get the number of bytes occupied by the field in a structure

1#define FSIZ( type, field ) sizeof( ((type *) 0)->field )

7. Convert two bytes into one Word according to LSB format

1#define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )

8. Convert a Word into two bytes in LSB format

1#define FLOPW( ray, val ) \
2(ray)[0] = ((val) / 256); \
3(ray)[1] = ((val) & 0xFF)

9. Get the address of a variable (word width)

1#define B_PTR( var ) ( (byte *) (void *) &(var) )
2#define W_PTR( var ) ( (word *) (void *) &(var) )

Get the upper and lower 10 bytes of a word

1#define WORD_LO(xxx) ((byte) ((word)(xxx) & 255))
2#define WORD_HI(xxx) ((byte) ((word)(xxx) >> 8))

11. Returns the nearest multiple of 8 larger than X

1#define RND8( x ) ((((x) + 7) / 8 ) * 8 )

12. Convert a letter to uppercase

1#define UPCASE( c ) ( ((c) >= 'a' && (c) <= 'z') ? ((c) - 0x20) : (c) )

13. Judge whether the character is a decimal digit

1#define DECCHK( c ) ((c) >= '0' && (c) <= '9')

14. Judge whether the character is a hexadecimal digit

1#define HEXCHK( c ) ( ((c) >= '0' && (c) <= '9') ||\
2((c) >= 'A' && (c) <= 'F') ||\
3((c) >= 'a' && (c) <= 'f') )

15. A method to prevent overflow

1#define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))

16. Number of elements returned from the array

1#define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )

17. Return the value mod of the N-tail of an unsigned number_ BY_ POWER_ OF_ TWO(X,n)=X%(2^n)

1#define MOD_BY_POWER_OF_TWO( val, mod_by ) \
2( (dword)(val) & (dword)((mod_by)-1) )

18. For the structure in which the IO space is mapped in the storage space, input and output processing

1#define inp(port) (*((volatile byte *) (port)))
2#define inpw(port) (*((volatile word *) (port)))
3#define inpdw(port) (*((volatile dword *)(port)))
4#define outp(port, val) (*((volatile byte *) (port)) = ((byte) (val)))
5#define outpw(port, val) (*((volatile word *) (port)) = ((word) (val)))
6#define outpdw(port, val) (*((volatile dword *) (port)) = ((dword) (val)))

19. Use some macros to trace debugging

The A N S I standard describes five predefined macro names. They are:

1_ L I N E _
2_ F I L E _
3_ D A T E _
4_ T I M E _
5_ S T D C _

If the compilation is not standard, only a few of the above macro names may be supported or not at all. Remember that the compiler may also provide other predefined macro names.
_ l i n e and F I L E_ Macro instructions are discussed in the section on # l i n e, and the remaining macro names are discussed here.
_ D AT E _ The macro instruction contains a string in the form of month / day / year, which represents the date when the source file is translated into the code.
The time when the source code is translated to the object code is included as a string_ T I M E _ Yes. The string form is: Minutes: seconds.
If the implementation is standard, the macro_ S T D C _ Contains decimal constant 1. If it contains any other number, the implementation is nonstandard.
You can define macros, for example, when_ DEBUG, output data information and the line of the file

1#ifdef _DEBUG
2#define DEBUGMSG(msg,date) printf(msg);printf("%d%d%d",date,_LINE_,_FILE_)
3#else
4#define DEBUGMSG(msg,date)
5#endif

20. The macro definition prevents errors in use and is contained in parentheses.

Example:

1#define ADD(a,b) (a+b)

Use the do{}while(0) statement to contain multiple statements to prevent errors
Example:

1#difne DO(a,b) a+b;\
2a++;

When applying:

1if(....)
2DO(a,b); //Generate error
3else

resolvent:

1#difne DO(a,b) do{a+b;\
2a++;}while(0)

Keywords: C

Added by HuggieBear on Fri, 04 Mar 2022 02:39:18 +0200