Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ANSI C Macros


Published on

Published in: Technology

ANSI C Macros

  1. 1. ANSI C Macros – The C PreprocessorS.SRIKRISHNANPRE - FINAL YEARSSN COLLEGE OF ENGINEERINGne of the features not included in the original C language was the concept ofconstants. In order to accommodate various features, (including constants),the authors of C developed the C preprocessor. None of the services providedby the C preprocessor (cpp) is indispensible for writing C programs, but these servicesmake the task considerably easier.Outline:1. How the preprocessor works2. The #define Directive3. Constants4. Macros5. Macros with Arguments6. The #undef Directive7. The #include Directive8. Conditional compilation : #ifdef, #ifndef, #endif9. Conditional compilation : #if, #else10.Predefined MacrosO
  2. 2. How The Preprocessor Works When you issue the command to compile a C program, the program is runautomatically through the preprocessor The preprocessor is a program that modifies the C source program accordingto the directives supplied in the program. The preprocessor does not modify the program file, but creates a new file thatcontains the processed version of the program. This new file is then submitted to the compiler.Fig(a) The Compilation ProcessIf a program contains the directive#define NULL 0,and the statementx = NULL;the preprocessor replaces every occurrence of NULL following the #define directivewith 0.The resulting program no longer includes the directive (since the directives areonly for the preprocessor, not the compiler), and the preceding statement now readsas follows:x = 0;Constants, therefore, are abbreviations supplied for the convenience of theprogrammer. Each occurrence of a constant is translated by the preprocessor so that
  3. 3. the program is comprehensible to the C compiler. The preprocessor can also delete oradd C program statements.Note: All preprocessor directives begin with the number or sharp sign (#). The directive is terminated not by a semicolon, but by the end of the line onwhich it appears. Only one directive can occur on a line. A preprocessor symbol is never replaced if it occurs within single or doublequotation marks. The preprocessor does not check for normal C syntax, except for identifyingquotation marks. It merely substitutes symbols where it finds them.The #define DirectiveThe #define directive is used to define a symbol to the preprocessor and assignit a value. The symbol is meaningful to the preprocessor only in lines of codefollowing the definition.For example, if the directive#define NULL 0,is included in the program, then in all lines following the definition, the symbol NULLis replaced by the symbol 0. If the symbol NULL is encountered before the definition,it is not replaced.The #define directive is followed by one or more spaces or tabs and the symbolto be defined. It cannot be a C keyword or an identifier, if it is, a syntax error isdetected by the compiler.For example, suppose the program contains the directive#define dumb 54which in turn is followed by the declaration
  4. 4. int dumb;This would be translated by the preprocessor intoint 54;which would be rejected by the compiler.If a #define directive does not fit on a single line, it can be continued onsubsequent lines. All lines of the directive except the last line must end with abackslash() character. A directive can be split only at a point where a space islegal.For example:#define max(a,b) ({ typeof (a) _a = (a); typeof (b) _b = (b); _a > _b ? _a : _b; })ConstantsA common use for defined symbols is the implementation of named constants.The following are the examples of constants in C: 25 1.23 „a‟ “hello” -6Any of these values can be assigned to a defined preprocessor symbol:#define INTEGER 25#define CHARACTER „a‟A defined symbol can specify only a complete constant. For example, if aprogram contains the definitions#define NULL 0the number 120 cannot be represented as 12NULL. A defined symbol can berecognized only if it is delimited by a white space, punctuation, or operators.(This rule also applies to C identifiers, such as variables or function names.)
  5. 5. MacrosThe following is a valid preprocessor directive.#define TEST if (a > b)The symbol TEST is defined to be the entire contents of the directive followingthe symbol TEST; that is the stringif (a > b)The statementTEST printf(“It workedn”);would be translated toif (a > b) printf(“It workedn”);Some programmers include the following definitions in all their programs:#define and &&#define or ||These definitions enable the programmer to write more readable code, such asthe following:if(a < b or c > d and e < f)Macros With ArgumentsThe C preprocessor permits macros with arguments, just as functions do.Consider the following example:#define Decrement(x) if(x > 0) x -= 1( Just like a function to return the decremented valu. Note: No values returned here)
  6. 6. Code 1:#include<stdio.h>#define Decrement(x) if(x>0) x-=1int main(void){int k=11;Decrement(k);char c=B;Decrement(c);printf("%X %c",k,c);return 1;}Output:A ACode 2:#include<stdio.h>#define NUM_PRINT(value,spec)printf(“value= %specn”,value)int main(void){int k=11;NUM_PRINT(k,d);return 1;}Output:value=11What if we have:#define NUM_PRINT(n,spec)printf(“n= %specn”,n)Code 3:#include<stdio.h>#define TOHUNDRED(x) (x * 100)void main(){int a=12,b=4;printf(“%d”,TOHUNDRED(a+b));}
  7. 7. Output:412Code 4:#include<stdio.h>#define sqr(a) ((a)*(a))int main(){int x=7;printf(“%c”,(char)sqr(x));return 1;}Output:1A macro can be defined in terms of another macro, as in the following exampleof nested macros:#define CONTROL “%dn”#define printint(x) printf(CONTROL,x)#define TEST(x) if(x>0) printint(x)If the program contains the statementTEST(w);where w is an integer variable, the statement goes through the following conversiontypes: if (w>0) printint(w); if (w>0) printf(CONTROL,w); if (w>0) printf(“%dn”,w);Note: A macro definition cannot contain itself, as in#define infinity infinity#define A B
  8. 8. #define B AThere are also serious limits to the preprocessor‟s ability to detect hidden recursion,so these errors might not be detected until the preprocessor attempts to make thesubstitutions and finds itself in an infinite loop.When macros and when functions? A function that would consist of only one line of code usually should beimplemented as a macro, to save computing time. If memory space is the primary consideration, however, a macro may not bethe best choice. Macros are more powerful than functions in that their arguments can be anystrings at all – They can be used with arguments of different types.The #include DirectiveOften a programmer accumulates a collection of useful constants and macrodefinitions that are used in almost every program. It is desirable to be able to storethese definitions in a file that can be inserted automatically into every program. Thistask is done by the #include directive.A file is inserted at any point where the #include directive is encountered.Such files are called as header files, and by convention their names end withcharacters „.h‟ (as in stdio.h).Header files can contain any text at all. Aside from preprocessor directives todefine macros, they may also contain C code to define structure templates, globalvariables, or function definitions.An example of an inclusion you have already seen is#include<stdio.h>in which stdio.h is the file to be included. The angular brackets tell the preprocessorto search for the file in one or more standard directories. These directories contain
  9. 9. the header files that are provided by the system. If the brackets are replaced withdouble quotation marks, as in#include “stdio.h”the preprocessor looks first in the programmer‟s own directory, or the same one thatcontains the program files. If it is not found there, then standard directories aresearched.Another common use of the header files is to provide consistency amongseveral program files. Often a program is so large that it is convenient to break itdown into smaller units, each of which is stored in a separate file. After theseseparate program files are compiled, they must somehow be linked together to form asingle file. This linking is usually accomplished by a program called the linkage editor,which is often run automatically when the program is compiled.A header file can contain other #include directives. It cannot include itself,because this would lead to infinite recursion. It cannot include another file thatincludes this file, as this would also lead to infinite recursion.C standard library <assert.h> <complex.h> <ctype.h> <errno.h> <fenv.h> <float.h> <inttypes.h> <iso646.h> <limits.h> <locale.h> <math.h> <setjmp.h> <signal.h>
  10. 10.  <stdarg.h> <stdbool.h> <stddef.h> <stdint.h> <stdio.h> <stdlib.h> <string.h> <tgmath.h> <time.h> <wchar.h> <wctype.h>The #undef DirectiveIt may be necessary to redefine a macro at some point in a program. Forexample, the user may wish to redefine a macro or constant specified in a header filesuch as stdio.h. If only a few macros from such a file need to be redefined, theeasiest way is to use #include the entire file and then redefine the macros in thequestion.For example, suppose the programmer wishes the constant EOF to have thevalue -2, the programmer could begin with the following directives:#include<stdio.h>#undef EOF#define EOF -2(In practice, it would be dangerous to redefine the value of EOF; it is donehere merely as an example)If a preprocessor symbol has already been defined, it must be undefined beforebeing redefined. This is accomplished by the #undef directive, which specifies thename of the symbol to be undefined.
  11. 11. It is not necessary to perform the redefinition at the beginning of a program. Asymbol can be redefined in the middle of a program, so that it has one value in thefirst half and another value at the end.A symbol need not be redefined after it is undefined. If the program uses thesymbol in a statement after the point at which it is undefined, however, the symbol isnot replaced. A defined symbol will be replaced before the point (if any) at which it isundefined.Conditional Compilation : #ifdef, #ifndef, #endifThe general idea behind conditional compilation is that a piece of code can beselectively compiled, depending upon whether a specific value has been #defined, ornot. Reasons for doing this vary, but the main ones seem to be: Platform specific constraints Debug builds Performance issues(When we talk of platform specific here, we mean flavors of the same platform,rather than different operating systems or hardware platforms.)In essence, the aim is to create a different executable file (application),depending on several flags that are set by the programmer. Although, as we shall see,the technique is also used to prevent multiple #includes, which generate errors duringthe compile process.If an #ifdef return a true value, all the lines between the #ifdef and thecorresponding #endif directive are left in the program. If those lines containpreprocessor directives, the directives are processed. If #ifdef evaluates as false, theassociated lines are ignored, including the preprocessor directives included.Even though we talk about conditional compilation directives in the same termsas the C if statement, the preprocessor directives are executed before thecompilation is initiated. Thus, there can be no overlap between the C code and thepreprocessor directives. For example, the #ifdef directive cannot be used to test forthe declaration of a variable.
  12. 12. The simplest sort of conditional is#ifdef NAME/* compile these lines if NAME is defined */#endif#ifndef NAME/* compile these lines if NAME is not defined */#endifSample piece of Code 1:#ifdef LINKED_LISTAdd_node(p,&inv_list);#endifSample piece of Code 2:#ifndef MAX_LEN#define MEX_LEN 1000#endifIf the programmer wants FLAG never to be defined, then the following can be done:#ifdef FLAG#undef FLAG#endifConditional Compilation : #if, #elif, #elseThere are 2 main disadvantages with the #ifdef and the #ifndef directives: It is not possible to test whether a symbol has a specific value. There are no connecting logical AND or OR operators.These are overcome by the more general #if - #else directive#ifdef name/*program text*/#else/*more program text*/#endif
  13. 13. Note: #elif is available only with the ANSI C preprocessor.#if A>47 // compiled if A is greater than 47#else#if A < 20 // compiled if A is less than 20#else // compiled if A is greater than or equal// to 20 and less than or equal to 47#endif // end of if, A is less than 20#endif // end of if, A is greater than 47Any undefined preprocessor symbol used in the #if expression is treated as if ithas the value 0.Predefined Macros:Macro Description__DATE__ The compilation date of the current source file. The date is a stringliteral of the form Mmm dd yyyy. The month name Mmm is the same asfor dates generated by the library function asctime declared in TIME.H.__FILE__ The name of the current source file. __FILE__ expands to a stringsurrounded by double quotation marks. To ensure that the full path tothe file is displayed, use /FC (Full Path of Source Code File inDiagnostics).__LINE__ The line number in the current source file. The line number is a decimalinteger constant. It can be changed with a #line directive.__STDC__ Indicates full conformance with the ANSI C standard. Defined as theinteger constant 1 only if the /Za compiler option is given and you arenot compiling C++ code; otherwise is undefined.__TIME__ The most recent compilation time of the current source file. The time isa string literal of the form hh:mm:ss.__TIMESTAMP__ The date and time of the last modification of the current source file,expressed as a string literal in the form Ddd Mmm Date hh:mm:ss yyyy,where Ddd is the abbreviated day of the week and Date is an integerfrom 1 to 31.Code:#include<stdio.h>int main(){printf("File :%stLine %dn",__FILE__,__LINE__);
  14. 14. printf("Date: %stTime: %sn",__DATE__,__TIME__);return 1;}Output:File :C:Documents and SettingsS.SrikrishnanDesktoptest.cLine 4Date: Sep 10 2010 Time: 15:09:28REFERENCES:Leland L. Beck, “System Software – An Introduction to Systems Programming”, 3rdEdition, Pearson Education Asia, 2006.Henry Mullish, Herbert L. Cooper, “The Spirit of „C‟ – An Introduction to ModernProgramming”, Jaico Publishing House.