|
Details of Preprocessor (GNU Preprocessor) 2014-12-17    Piotr Romaniuk, Ph.D. Contents
Macros Arguments Following rules are applied to arguments of macros:
// Macro with arguments #define SOME_MACRO( x, y, z) x+y+z // Macro with variable number of arguments (variadic macro) #define VAR_ARGS_MACRO(fun,...) fun( __VA_ARGS__ ) // Example of using the macro with unspecified argument #define CALL_FN( fun, arg1 ) fun( arg1 ) CALL_FN( send_char, mychar ); => send_char(mychar); DEV_CTX( get_char,); => get_char(); // Example of macro with a comma that is not arguments separator but is a part of argument: #define DBG( level, msg_args ) do{\ printf( "<%d> ", level);\ printf msg_args;\ }while[0] DBG( MSG_CRITICAL, ("%s %d", txt, nr) ); // Definition and usage of the macro with argument that contains a comma: #define CRIT_ENVELOPE( call ) do{ sys_disable_irq();\ call;\ sys_enable_irq();\ }while[0] CRIT_ENVELOPE( get_scheduler_state( &context, &result ) ); Two latter examples illustrates how to write multiline macro definition. It makes macro definition more clear, easy to read and understand. Nevertheless it has no influence on macro expansion - the expansion is always in one line. If you browse intermediate file that is preprocessing output: #61 "test.c" do{ sys_disable_irq(); get_scheduler_state( &context, &result ); sys_enable_irq();}while[0]; Do-while(0) envelope should be explained. The purpose of that is to force semicolon after macro usage in source code. (it will be discussed in separated description) Please note, that arguments that appear in strings in macro body are not expanded. #define SOME_MACRO(x) x, "x" //above macro will be expanded to: SOME_MACRO( 123 ) => 123, "x" If contents of the argument is needed as a string it should be stringified (see stringification operator). When the preprocessor finds the macro usage that must be expanded it does following operations:
#define GET_CHAR_RETTYPE void #define GET_CHAR_FN get_char #define get_char_void sys_get_char(&gctx) #define GET( fn, rtype ) fn ## _ ## rtype GET( GET_CHAR_FN, GET_CHAR_RETTYPE) //will be expanded to: GET_CHAR_FN_GET_CHAR_RETTYPE In order to have expansion of arguments as well, another macro must be added: #define _GET( fn, rtype ) fn ## _ ## rtype #define GET( fn, rtype ) _GET( fn, rtype ) GET( GET_CHAR_FN, GET_CHAR_RETTYPE) //it will be expanded to: sys_get_char(&gctx) Below is an example of recursion and the preprocessor behavior:: #define RECUR( x ) RECUR( x+2 ) // expansion with recursion is macro body: RECUR( a ) => RECUR( a+2 ) // and in argument: RECUR( RECUR( a ) ) => RECUR( RECUR( a+2 )+2 ) Spaces are not tokens for preprocessor but rather separators, it means that they are merged together and eliminated. #define M( x, y ) fun(x,y) //each following usage: M(1,2) M( 1,2) M(1, 2) M(1,2 ) M( 1 , 2 ) M (1,2) //will be expanded to the same result: fun(1,2) Spaces in argument list in macro definition are threated similar way: //these two definitions: #define MM_1(x,y) fun(x,y) #define MM_2( x, y ) fun(x,y) MM_1(20,30) MM_2(20,30) // are expanded to the same result: fun(20,30) fun(20,30) The difference is macro body, spaces from there are copied as they appear (multiple spaces are merged in one), unless they are close to concatenation operator (they are dropped): #define MM(x,y) fun( x , y) MM(1,2) => fun( 1 , 2) #define MCON(x,y) fun( x ## y ) MCON(a,b) => fun( ab ) The last but not least the note about spaces (consider it to be VERY IMPORTANT) in macro definition located between the macro name and argument list (exactly before opening bracket). When the space is put there it changes the type of the macro. It is recognized as object-like macro, argument-less one. Following argument list becomes a part of macro body, hence arguments are not substituted but appears as text like in definition. // Example of macro with extra space after name (this is an error) - it is interpretted as argument-less // parethesis is a part of macro body #define MACRO1 (x, y) x+y MACRO1(1,2) //above macro is expanded to: (x, y) x+y(1,2)
Links
|
||||||