Let's take a look at the simple initial code: Pay attention to the compiled and running results.
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat global. h // header file
# Ifndef clobal_h
# Define global_h
# Include <stdio. h>
Int funca (void );
Int funcb (void );
# Endif
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat funca. C // function
# Include "Global. H"
Int funca (void)
{
Printf ("this is function \ n ");
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat funcb. C // function B
# Include "Global. H"
Int funcb (void)
{
Printf ("this is function \ n ");
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # gcc-wall funca. c funcb. C main. C // Compilation
Root @ xuanfei-desktop :~ /Cpropram/2 #./A. Out // run
This is main
This is
This is main
This is Function
This is main
It is difficult to see the error in the same result. Next we will use _ file __,__ line __,__ function _ to add the code to see if there is any difference.
Add _ file __,__ line __,__ function _ to mail. C.
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat main. c
# Include "Global. H"
Int main (INT argc, char ** argv)
{
Printf ("% s (% d)-% S: This is main \ n" ,__ file __,__ line __,__ function __);
Funca ();
Printf ("% s (% d)-% S: This is main \ n" ,__ file __,__ line __,__ function __);
Funcb ();
Printf ("% s (% d)-% S: This is main \ n" ,__ file __,__ line __,__ function __);
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # gcc-wall funca. c funcb. C main. c
Root @ xuanfei-desktop :~ /Cpropram/2 #./A. Out
Main. C (4)-Main: This is main
This is Function
Main. C (6)-Main: This is main
This is Function
Main. C (8)-Main: This is main
The above result main. C (4)-Main: This is main indicates that this is main printed in the fourth line of main function of Mian. C source code.
In this case, it is very convenient for programmers to correct their own programs!
To make it easier to use, we can implement macro definition in the global. H code.
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat global. h
# Ifndef clobal_h
# Define global_h
# Include <stdio. h>
Int funca (void );
Int funcb (void );
# Define debugfmt "% s (% d)-% s"
# Define debugargs _ file __,__ line __,__ function __
# Endif
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat funca. c
# Include "Global. H"
Int funca (void)
{
Printf (debugfmt "this is function \ n", debugargs );
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat funcb. c
# Include "Global. H"
Int funcb (void)
{
Printf (debugfmt "this is function \ n", debugargs );
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # Cat main. c
# Include "Global. H"
Int main (INT argc, char ** argv)
{
Printf (debugfmt "this is main \ n", debugargs );
Funca ();
Printf (debugfmt "this is main \ n", debugargs );
Funcb ();
Printf (debugfmt "this is main \ n", debugargs );
Return 0;
}
Root @ xuanfei-desktop :~ /Cpropram/2 # gcc-wall funca. c funcb. C main. c
Root @ xuanfei-desktop :~ /Cpropram/2 #./A. Out
Main. C (4)-mainthis is main
Funca. C (4)-funca this is function
Main. C (6)-mainthis is main
Funcb. C (4)-funcb this is function
Main. C (8)-mainthis is main
Root @ xuanfei-desktop :~ /Cpropram/2 #
This is to define the _ file __,__ line __, function _ macro to easily implement code tracking and debugging :)
The following is a header file for trial debugging.
# Ifndef _ gold_debug_h
# DEFINE _ gold_debug_h
# Ifdef _ cplusplus
# If _ cplusplus
Extern "C "{
# Endif
# Endif/* _ cplusplus */
// # Define gi_debug
# Ifdef gi_debug
# Define gi_debug_point () printf ("\ n [file: % s line: % d] Fun: % s \ n", _ file __, _ line __, _ function __)
# Define dbg_printf (Arg...) printf (ARG );
# Define gi_assert (expr )\
Do {\
If (! (Expr )){\
Printf ("\ nassert failed at: \ n> file name: % s \ n> function: % s \ n> line No.: % d \ n> condition: % s \ n ",\
_ File __,__ function __, _ line __, # expr );\
}\
} While (0 );
/* Debug macro, used to pause */
# Define gi_debug_pause ()\
Do \
{\
Gi_debug_point ();\
Printf ("Pause for debug, press 'q' to exit! \ N ");\
Char C ;\
While (C = getchar ()))\
{\
If ('q' = C )\
{\
Getchar ();\
Break ;\
}\
}\
} While (0 );
# Define gi_debug_pause_arg (Arg ...)\
Do \
{\
Printf (ARG );\
Gi_debug_pause ()\
} While (0 );
# Define gi_debug_assert (expression )\
If (! (Expression ))\
{\
Printf ("[assert], % s, % s: % d \ n", _ file __, _ FUNCTION __, _ line __);\
Exit (-1 );\
}
# Else
# Define gi_assert (expr)
# Define gi_debug_pause ()
# Define gi_debug_pause_arg (Arg ...)
# Define gi_debug_point ()
# Define dbg_printf (Arg ...)
# Define gi_debug_assert (expression)
# Endif
# Ifdef _ cplusplus
# If _ cplusplus
}
# Endif
# Endif/* _ cplusplus */
# Endif
01: prevent a header file from being repeatedly contained
# Ifndef comdef_h
# Define comdef_h
// Header file content
# Endif
02: redefines 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 */
03: Get a byte or word on the specified address
# Define mem_ B (x) (* (byte *) (x )))
# Define mem_w (x) (* (word *) (X )))
04: calculate the maximum and minimum values
# Define max (x, y) (x)> (y ))? (X): (y ))
# Define min (x, y) (x) <(y ))? (X): (y ))
05: Get the offset of a field in the struct (struct ).
# Define FPOs (type, field) (DWORD) & (type *) 0)-> field)
06: Get the number of bytes occupied by field in a struct.
# Define fsiz (type, field) sizeof (type *) 0)-> field)
07: convert two bytes into a word in LSB format
# Define flipw (Ray) (Word) (Ray) [0]) * 256) + (Ray) [1])
08: convert a word into two bytes in LSB format
# Define flopw (Ray, Val) (Ray) [0] = (VAL)/256); (Ray) [1] = (VAL) & 0xff)
09: Get the address of a variable (word width)
# Define B _ptr (VAR) (byte *) (void *) & (VAR ))
# Define w_ptr (VAR) (word *) (void *) & (VAR ))
10: Get 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: returns a multiple of 8 nearest to X.
# Define rnd8 (x) + 7)/8) * 8)
12: convert a letter to uppercase
# 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 an unsigned number N 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 ing in the bucket structure, 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 )))
19: use some macro tracking for debugging
The ANSI standard specifies five predefined macro names. They are:
_ Line __
_ File __
_ Date __
_ Time __
_ Stdc __
C ++ also defines _ cplusplus
If the compiler is not standard, only a few of the above macro names are supported or not supported at all. Remember that the Compilation Program may also provide other predefined macro names.
_ Line _ and _ file _ macro instructions. # The line command can change its value. In short, during compilation, it contains the current number of lines and file names of the program.
The _ date _ 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 _ macro command contains the program Compilation Time. Time is represented by a string in the form of minute: Second
The significance of the _ stdc _ macro command is defined during compilation. Generally, if _ stdc _ has been defined, the compiler will only accept standard C/C ++ code that does not contain any non-standard extensions. If the implementation is standard, macro _ stdc _ contains the decimal constant 1. If it contains any other number, the implementation is non-standard.
The consistent compiler of _ cplusplus and Standard C ++ defines it as a value containing at least six characters. A compiler that is inconsistent with the standard C ++ will use a value of 5 or less.
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 the use of parentheses for inclusion.
For example:
Definition in question: # define dump_write (ADDR, NR) {memcpy (bufp, ADDR, NR); bufp + = nR ;}
Definition: # difne do (a, B) do {A + B; A ++;} while (0)
For example:
If (ADDR)
Dump_write (ADDR, NR );
Else
Do_somethong_else ();
This will happen after the macro scale:
If (ADDR)
{Memcpy (bufp, ADDR, NR); bufp + = nR ;};
Else
Do_something_else ();
When GCC encounters the ";" in front of Else, it considers that the if statement has ended, so the subsequent else is not in the IF statement. With the do {} while (0) definition, there is no problem under any circumstances. The definition of # difne do (a, B) do {A + B; A ++;} while (0) will not go wrong under any circumstances.