I remember in the previous article, I analyzed the <assert. h> in a heap of windows. Today, let's take a look at the definition of this file in GCC.
[1] role of assert macro
The role of assert macro to implement assertions is generally referenced in the source file in the following format:
# Include <assert. h># UNDEFNdebugAssert (expression)
About assert macro:
1. When expression is 0, assertion is performed. If expression is non-zero, assertion is not performed.
2. When assert macro performs assert, output the source file name __file _ in the standard error output and the row of the statement when the assert occurs: _ line __
3.ProgramDuring the debugging process, the assert macro is used to test the key program to output some useful information. When debugging is not required, you can define the ndebug macro to cancel it.
The role of macro assert.
[2] assert. h
/* Allow this file to be compiled ded multiple times with different settings of ndebug. */ // Assert is an assertion mechanism provided by C library. // Assertions are used to output stream output information in a standard error and terminate an exception in the program. /* Assertion mechanism: */ // First, cancel the definition of the assert macro, // The purpose is to prevent macro duplication from being defined. # UNDEF Assert # UNDEF _ Assert // Determine whether the ndebug macro is negative.Source codeWhether macro assert is required /* If the ndebug macro is defined, it means that you do not need to reference the assert macro ndebug: Do not debug in the program. Otherwise, the assert Macro will be executed and we can find that when the assert macro defines ndebug, the definition is special. macro parameters are not referenced. */ # Ifdef ndebug // Ndebug macro is defined, and assert macro is defined as no prompt output # Define Assert (ignore) (void) 0) # Else Void _ Eprintf (); /* Defined in gnulib */ # Ifdef _ stdc __ // The _ stdc _ macro is defined. # Define Assert (expression )\ (( Void ) (Expression )? 0 : _ Assert (# expression, _ file __, _ line __))) # Define _ Assert (expression, file, lineno )\ (_ Eprintf ( " Failed assertion '% s' at line % d of' % s'. \ n " , \ Expression, lineno, file ), 0 ) # Else /* No _ stdc __; I. e.-Traditional .*/ # Define Assert (expression )\ (( Void ) (Expression )? 0 : _ Assert (expression, _ file __, _ line __))) # Define _ Assert (expression, file, lineno )\ (_ Eprintf ( " Failed assertion '% s' at line % d of' % s'. \ n " ,\ " Expression " , Lineno, file ), 0 ) # Endif /* No _ stdc __; I. e.-Traditional .*/ # Endif
View code
[3] preprocessing
//First, cancel the definition of the assert macro,//The purpose of this operation is to prevent the impact of repeated definition macros.# UNDEFAssert# UNDEF_ Assert
The purpose of this operation is to prevent assert redefinition and confusion. In this way, the previous definition can be canceled at the referenced position.
[4] standard assert macro definition structure
Generally, the assert macro definition has the following structure:
The purpose of this structure is to make a correct response to the user's ndebug macro.
[5] macroCode
// Determine whether macro assert is required in the source code by checking whether ndebug is a negative macro. /* If the ndebug macro is defined, it means that you do not need to reference the assert macro ndebug: Do not debug in the program. Otherwise, the assert Macro will be executed and we can find that when the assert macro defines ndebug, the definition is special. macro parameters are not referenced. */ # Ifdef ndebug // Ndebug macro is defined, and assert macro is defined as no prompt output # Define Assert (ignore) (void) 0) # Else Void _ Eprintf (); /* Defined in gnulib */ # Ifdef _ stdc __ // The _ stdc _ macro is defined. # Define Assert (expression )\(( Void ) (Expression )? 0 : _ Assert (# expression, _ file __, _ line __))) # Define _ Assert (expression, file, lineno )\ (_ Eprintf ( " Failed assertion '% s' at line % d of' % s'. \ n " , \ Expression, lineno, file ), 0 ) # Else /* No _ stdc __; I. e.-Traditional .*/ # Define Assert (expression )\ (( Void ) (Expression )? 0 : _ Assert (expression, _ file __, _ line __))) # Define _ Assert (expression, file, lineno )\ (_ Eprintf ( " Failed assertion '% s' at line % d of' % s'. \ n " ,\ " Expression " , Lineno, file ), 0 ) # Endif /* No _ stdc __; I. e.-Traditional .*/ # Endif
Here we can see that this macro actually defines two red keys: assert and _ assert.
1. Assert
There are two situations:
When _ stdc _ macro is defined:
# DefineAssert (expression )\((Void) (Expression )?0: _ Assert (# expression, _ file __, _ line __)))
When _ stdc _ macro is not defined:
# DefineAssert (expression )\((Void) (Expression )?0: _ Assert (expression, _ file __, _ line __)))
The difference between the two lies only in the role of the "#" connector. If the form # expression is not used, the macro parameter cannot use a string with quotation marks.
# Expression. The actual assert macro parameter can be a string with quotation marks.
Two predefined macros:
_ File __: return the source file name of the C member.
_ Line _: return the number of lines in the C file of the code line.
2. _ assert
This macro has only one form:
# Define_ Assert (expression, file, lineno )\(_ Eprintf ("Failed assertion '% s' at line % d of' % s'. \ n",\"Expression", Lineno, file ),0)
This macro actually references the function _ eprintf () to implement the output. This function is not a standard library function. If you want to implement the standard assert macro, you cannot reference the standard library
Function implementation, because if the program does not contain these library functions, it will cause an exception.
_ Eprintf () function:
# Ifdef l_eprintf # include <Stdio. h> /* This is used by the 'assert 'macro. */ Void _ Eprintf ( String , Expression, line, filename) Char * String ; Char * Expression; Int Line; Char * Filename; {fprintf (stderr, String , Expression, line, filename); fflush (stderr); abort ();} # Endif
That is to say, this header file can also be like this:
# Ifdef ndebug // Ndebug macro is defined, and assert macro is defined as no prompt output # Define Assert (ignore) (void) 0) # Else Void _ Eprintf (); /* Defined in gnulib */ # Define _ Assert (expression, file, lineno )\(_ Eprintf ( " Failed assertion '% s' at line % d of' % s'. \ n " , \ Expression, lineno, file ), 0 ) # Ifdef _ stdc __ // The _ stdc _ macro is defined. # Define Assert (expression )\ (( Void ) (Expression )? 0 : _ Assert (# expression, _ file __, _ line __))) # Else /* No _ stdc __; I. e.-Traditional .*/ # Define Assert (expression )\ (( Void ) (Expression )? 0 : _ Assert (expression, _ file __, _ line __))) # Endif /* No _ stdc __; I. e.-Traditional .*/ # Endif
[6] comparison of Microsoft vs 2008 code
/* * ** Assert. h-define the assert macro ** copyright (c) Microsoft Corporation. all rights reserved. ** purpose: * defines the assert (exp) Macro. * [ANSI/System V] ** [public] ***** */ # Include <Crtdefs. h> # UNDEF Assert # Ifdef ndebug # Define Assert (_ expression) (void) 0) # Else # Ifdef _ cplusplus Extern " C " { # Endif _ Cribd Void _ Cdecl _ wassert (_ in_z _ Const Wchar_t * _ message, _ in_z _ Const Wchar_t * _ File, _ in _ unsigned _ line); # ifdef _ cplusplus} # Endif # Define Assert (_ expression) (void )((!! (_ Expression) | (_ wassert (_ crt_wide (# _ expression), _ crt_wide (_ file _), _ line _), 0 )) # Endif /* Ndebug */
I don't know. Are there any books dedicated to the source code of the GCC compiler? I know there is a GCC internal, which is an English version. It seems useless. Does anyone know such a book in Chinese;
the man did not give me any advice. He told me a book like this, or a forum like this. I haven't found a consensus for a long time.