110 likes | 450 Views
Macro. A fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. Two kinds of macros Object-like Functon -like
E N D
Macro • A fragment of code which has been given a name. • Whenever the name is used, it is replaced by the contents of the macro. • Two kinds of macros • Object-like • Functon-like • You may define any valid identifier as a macro, even if it is a C keyword. The preprocessor does not know anything about keywords.
Object-like Macros • A simple identifier which will be replaced by a code fragment. • Most commonly used to give symbolic names to numeric constants. #define BUFFER_SIZE 1024 … foo = (char *) malloc (BUFFER_SIZE); #define BUFFER_SIZE 1024 … foo = (char *) malloc (1024); C preprocessor
Object-like Macros • By convention, macro names are written in uppercase. • The macro’s body ends at the end of the ‘#define’ line. • You may continue the definition onto multiple lines, if necessary. #define NUMBERS 1, \ 2, \ 3 int x[] = { NUMBERS }; int x[] = { 1, 2, 3 };
Object-like Macros • The C preprocessor scans your program sequentially. • Macro definitions take effect at the place you write them. foo = X; #define X 4 bar = X; foo = X; bar = 4; TABLESIZE BUFFSIZE 1024 #define TABLESIZE BUFFSIZE #define BUFFSIZE 1024
Function-like Macros • Use the same ‘#define’ directive, but put a pair of parentheses immediately after the macro name. #define lang_init() c_init() … lang_init() c_init() • If you put spaces between the macro name and the parentheses in the macro definition, that does not define a function-like macro. It defines an object-like macro. #define lang_init () c_init() … lang_init() () c_init()()
Macro Arguments • To define a macro with arguments, insert parameters between the pair of parentheses. #define min(X, Y) ((X)<(Y) ? (X):(Y)) x = min(a, b); -> x = ((a)<(b) ? (a):(b)); y = min(1, 2); -> y = ((1)<(2) ? (1):(2)); z = min(a + 28, *p) -> z = ((a + 28)<(*p) ? (a + 28):(*p)); • You can leave macro arguments empty, but cannot leave out arguments entirely. min(, b); -> (( )<(b) ? ( ):(b)); min(a, ); -> ((a)<( ) ? (a):()); min(,); -> (( )<( ) ? ( ):()); min() -> error macro “min” requires 2 arguments, but only 1 given
Undefining and Redefining Macros • If a macro ceases to be useful, it may be undefined with the “#undef” directive, which takes a single argument, the name of the macro to undefine. Use the bare macro name, even if the macro is function-like. #define FOO 4 x = FOO; -> x = 4; #undef FOO x = FOO -> x = FOO; • Once a macro has been undefined, that identifier may be redefined as a macro by a subsequent “#define” directive.
The following is strcpy() function using pointers. strcpy(s, t) /* copy t to s; pointer version */ { char *s, *t; while (*s ++ = *t ++) ; } Write a macro for strcpy.
Solution 1 (segmentation fault) #include <stdio.h> #define strcpy(x,y) while (*x ++ = *y ++); int main(void) { char *s, *t; t = "abc"; strcpy(s,t); printf("%s\n", s); return 0; }
Solution 2 (segmentation fault) #include <stdio.h> #define strcpy(x,y) {char *tempA = x; while (*tempA ++ = *y ++);} int main(void) { char *s, *t; t = "abc"; strcpy(s,t); printf("%s\n", s); return 0; }
Solution 3 (Finally working!) #include <stdio.h> #define strcpy(x,y) {char *tempA = x; while (*tempA ++ = *y ++);} int main(void) { char s[10], *t; t = "abc"; strcpy(s,t); printf("%s\n", s); return 0; }