------------------------------------------------------------------------------- What macros are pre-defined Gcc at least man probably other compilers will list the predefined macros which given a -v option EG: gcc -v hello_world.c Reading specs from /usr/lib/gcc-lib/i486-linux/egcs-2.91.66/specs gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release) /usr/lib/gcc-lib/i486-linux/egcs-2.91.66/cpp -lang-c -v -undef -D__GNUC__=2 -D__GNUC_MINOR__=91 -D__ELF__ -Dunix -Di386 -D__i386__ -Dlinux -D__ELF__ -D__unix__ -D__i386__ -D__i386__ -D__linux__ -D__unix -D__i386 -D__linux -Asystem(posix) -Asystem(unix) -Acpu(i386) -Amachine(i386) -Di386 -D__i386 -D__i386__ -D__tune_i486__ ------------------------------------------------------------------------------- Concatation Macro This marco is used to concatate two identifiers together into one identifier for the compler. This macro is normally defined in ansi C include files: memvar.h. #ifndef CAT # undef IDENT # define IDENT(x) x # ifdef __STDC__ # define CAT(a,b) a##b # else # define CAT(a,b) IDENT(a)b # endif #endif ------------------------------------------------------------------------------- BSD to SysV Marco converters For System V machine /* SysV memcpy for bcopy (note argument positions) */ #define bcopy(s,d,n) memcpy(d,s,n) #define bzero(p,n) memset(p,'\0',n) #define index(p,c) strchr(p,c) For BSD #define memcpy(d,s,n) bcopy(s,d,n) ------------------------------------------------------------------------------- Tests on string defines Cpp normall can not compare string defines. However through the use of some carefully trickery it can be done EG: #define anthony 1 ! any number other than 0 would work here #define jonh 2 ! any different number here #if USER == anthony # define AUTHOR "Anthony Thyssen" #elif USER == john # define AUTHOR "John Doe" #endif #undef anthony ! don't forget or other problems may occur #undef john Idea (for X resources) by: Johnny Tolliver jxt@ca12.cad.ornl.gov ------------------------------------------------------------------------------- Rules for writing C macros. * never put a final `;' on the end of a macro -- let the caller provide this. * Bracket all arguments and the total macro expression. This avoids Bad Case: #define multiply(a,b) a * b multiply(5,2+10) --> 5 * 2 + 10 --> 20 Corrected: #define multiply(a,b) ( (a) * (b) ) multiply(5,2+10) --> ( (5)*(2+10) ) --> 60 * If possible only use a argument once to avoid expression duplication and thus duplication of side effects, such as pre/post increments. Example: #define abs(x) ( (x)>0 ? (x) : -(x) ) abs( i++ ); /* i will be double incremented by the macro! */ To stop this assign the expression argument given to a temporary variable and thus only evaluating that expression only once. EG: int tmp; /* temporary variable for macro */ #define assign(ary,int) ( tmp = (int), ary[tmp] = tmp ) assign(my_array, i++); /* i is not double incremented */ * Expression Macros... Expression macros, are numerical expressions that "return" a result into the code where they are placed. These macros are the most common type of macro in use and is characterized by the use of brackets (...). Problems with Expression Macros:- * No looping or recursion. * No variable declarations * can be very obtusicated * be careful about argument side effects (like increment) * Proceedural macros... Proceedural macros, allow the use of loops and variable declarations and usually consist of a brace block {...} to group all the statements, This is to avoid problems with looping statements and within if constructs. For example (bad)... #define swap(a,b) { int t=a; a=b; b=t; } However C syntax does NOT permit a `;' to be placed after the close brace when an else follows... For example using the above brace macro... if (x