Some object macros are defined in standard C and each compiler. These macros start and end with "_" and are all uppercase characters. these predefined macros can be # UNDEF or redefined.
The _ file __,__ line __,__ data __,__ time __,__ stdc _ Standard predefined macros are defined in the ansi c standard. GCC extends it and defines multiple predefined macros.
In summary, the predefined macros available in GCC cover the following information:
1. host information: GNU version, compiler version, type information, and byte sequence information.
2. compile action information: Date and time of compilation, whether time or space optimization is performed during compilation, and whether the defined inline is executed by the compiler.
3. File Information: file name, function name, number of lines, and last file modification time.
4. Count information: __counter __,__ include_level.
Below are some common methods to use predefined macros.
1. _ file __,__ line __, function __
This is the most commonly used combination of predefined macros, indicating the file name, number of lines, and function name, used for tracking exceptions during running. For example:
// ------- File main. c ---------- <br/> # include <stdio. h> <br/> # include "myassert. H "</P> <p> int func (const char * filename); </P> <p> int main (INT argc, char ** argv) <br/>{< br/> myassert ("Two ARGs are needed", argc = 2); <br/> func (argv [1]); <br/> return 0; <br/>}</P> <p> // ------- file func. c ---------- <br/> # include <sys/types. h> <br/> # include <sys/STAT. h> <br/> # include <fcntl. h> <br/> # include <unistd. h> <br/> # Include "myassert. H "</P> <p> int func (const char * filename) <br/>{< br/> int FD; <br/> myassert ("filename can not be null", filename); <br/> myassert ("file not exist", 0 = access (filename, f_ OK )); <br/> FD = open (filename, o_rdonly); <br/> close (FD); <br/> return 0; <br/>}</P> <p> // ------- file myassert. h ---------- <br/> # ifndef _ my_assert_h __< br/> # DEFINE _ my_assert_h __</P> <p> # include <stdio. h> <br/> # In Clude <stdlib. h> </P> <p> # define myassert (message, assertion) do {/<br/> If (! (Assertion) {/<br/> printf ("line % d in % s (% s)", _ line __, _ file __, __function _);/<br/> If (Message) {/<br/> printf (": % s", message ); /<br/>}/ <br/> printf ("/N");/<br/> abort (); /<br/>}/ <br/>} while (0 ); <br/> # endif </P> <p> # makefile <br/> Target = test <br/> cc = GCC <br/> ccflags =-wall <br/> objs = Main. O func. O </P> <p> $ (target): $ (objs) <br/> $ (CC)-o $ @ $ (objs) $ (ccflags) </P> <p> %. o: %. c <br/> $ (CC)-o $ @-C $ <$ (ccflags) </P> <p> clean: <br/> RM-RF *. O <br/> RM-RF $ (target) <br/>
When running./tset:
Line 9 in Main. C (main): Two argvs are needed
Aborted
When running./test KKK:
Line 12 in func. C (func): file not exist
Aborted
Run./test successfully.
It can be seen that using the _ file __,__ line __, function _ macro can help us locate the file, function, and number of rows with exceptions precisely.
2. _ base_file __
This macro corresponds to _ file _, indicating the name of the main input file. For source files, _ file _ and _ base_file _ are the same; the header files may be different. For example, in the previous example, the _ line _ macro is defined in the myassert. h file and is included by main. C and func. C and the value of _ file _.
It is changed to main. C and func. C respectively. But when we want to know which file (actually myassert. h) the macro is defined, we need to use _ base_file __.
The following example can help you better understand the problem:
// ------- File main. c ---------- <br/> # include <stdio. h> <br/> # include "basefile. H "</P> <p> int main (INT argc, char * argv []) <br/> {<br/> printf (" % s/n ", sfile); <br/> printf ("% s/n", hfile); <br/> return 0; <br/>}</P> <p> // ------- file basefile. h ---------- <br/> const char sfile [] = _ file __; <br/> const char hfile [] = _ base_file __;
GCC main. C &./A. Out to get:
Basefile. h
Main. c
3. _ date __,__ time __
Used to obtain the date and time of the last compilation (in string format ):
# Include <stdio. h> <br/> // ------- file main. c ---------- <br/> int main () <br/>{< br/> printf ("Date: % s/n" ,__ date __); <br/> printf ("Time: % s/n" ,__ time _); <br/>}
GCC main. C &./A. Out to get:
Date: Jan 27 2011
Time: 17:12:55
4. _ timestamp __
The format is the same as that of _ time. The last modification time of this file.
5. _ gnuc _, _ gnuc_minor _, _ gnuc_minor _, and _ gnuc_patchlevel __
To obtain the GNU version:
# Include <stdio. h> <br/> int main () <br/> {<br/> If (_ gnuc _> 4 | <br/> (_ gnuc _ = 4 & (_ gnuc_minor _ _> 2 | <br/> (_ gnuc_minor _ = 2 & _ gnuc_patchlevel _> 0 )))) {<br/> printf ("gnuc version is later than 3.3.2/N "); <br/>}else {<br/> printf ("gnuc version is older than 3.3.2/N"); <br/>}< br/>}
6. _ version __
Used to obtain the compiler version
// ------- File main. c ---------- <br/> # include <stdio. h> <br/> int main () <br/> {<br/> printf ("version: % s/n" ,__ version __); <br/> return 0; <br/>}
GCC main. C &./A. Out to get:
Version: 4.1.2 (Gentoo 4.1.2 p1.0.2)
It can be verified with GCC-v.
7. _ counter __
It records the number of _ counter _ times in the previous compilation process and starts counting from 0. It is often used to construct a series of variable names and function names. For example:
// ------- File main. c ---------- <br/> # include <stdio. h> </P> <p> # define func2 (x, y) x # Y <br/> # define func1 (x, y) func2 (x, y) <br/> # define func (x) func1 (x ,__ counter _) </P> <p> int func (VAR ); <br/> int func (VAR); </P> <p> int main () {<br/> var0 = 0; <br/> var1 = 1; <br/> printf ("% d/N", var0); <br/> printf ("% d/N", var1); <br/> return 0; <br/>}
GCC main. C & A. out:
0
1
Here, _ counter _ is used to construct two variables: var0 and var1.
8. _ include_level __
Used to indicate the number of contained files, which increases progressively from 0 and is often used as a limit for Recursive inclusion. For example:
// ------- File main. c ---------- <br/> # include <stdio. h> <br/> int main () <br/>{< br/> # define rep_limit 10 <br/> # define rep (blah) printf ("% d ", blah); <br/> # include "rep. H "<br/> printf ("/N "); <br/> return 0; <br/>}</P> <p> // -------- file rep. h ---------- <br/> # If _ include_level _ <rep_limit <br/> rep (_ include_level _) <br/> # include "rep. H "<br/> # endif
GCC main. C &./A. Out. The result is as follows:
1 2 3 4 5 6 7 8 9
In this example, the file rep. h contains nine times and executes nine times rep (blah ).
In fact, _ include_level _ is used in combination with # include _ file _ to represent a recursion. For example:
// ------- File main. c ---------- <br/> # ifndef autoinc <br/> # define autoinc </P> <p> # include <stdio. h> <br/> # define max_level 10 <br/> int main () <br/> {<br/> int I = 0; <br/> # include _ file __< br/> printf ("/N"); <br/> return 0; <br/>}< br/> # UNDEF autoinc <br/> # endif </P> <p> # ifdef autoinc <br/> # If _ include_level _ <= max_level <br/> printf ("% d ", __include_level _); <br/> # include _ file __</P> <p> # If __ Include_level __! = Max_level <br/> printf ("% d" ,__ include_level _); <br/> # endif </P> <p> # endif <br/> # endif
GCC main. C &./A. Out. The result is as follows:
1 2 3 4 5 6 7 8 9 10 9 8 6 5 4 3 2 1
Refer:
Http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html#Standard-Predefined-Macros
Http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros