The preprocessor define directive directs the preprocessor to replace all subsequent occurrences of a macro with specified replacement tokens.
The define directive has the form:
>>-#--define--identifier--+--------------------------+----------> | .-,--------------. | | V | | '-(----+------------+-+--)-' '-identifier-' .----------------. V | >----+------------+-+------------------------------------------>< +-identifier-+ '-character--'
The define directive can contain an object-like definition or a function-like definition.
An object-like macro definition replaces a single identifier with the specified replacement tokens. The following object-like definition causes the preprocessor to replace all subsequent instances of the identifier COUNT with the constant 1000:
#define COUNT 1000
If the statement
int arry[COUNT];
appears after this definition and in the same file as the definition, the preprocessor would change the statement to
int arry[1000];
in the output of the preprocessor.
Other definitions can make reference to the identifier COUNT:
#define MAX_COUNT COUNT + 100
The preprocessor replaces each subsequent occurrence of MAX_COUNT with COUNT + 100, which the preprocessor then replaces with 1000 + 100.
If a number that is partially built by a macro expansion is produced, the preprocessor does not consider the result to be a single value. For example, the following will not result in the value 10.2 but in a syntax error.
#define a 10 a.2
Using the following also results in a syntax error:
#define a 10 #define b a.11
Identifiers that are partially built from a macro expansion may not be produced. Therefore, the following example contains two identifiers and results in a syntax error:
#define d efg abcd
A function-like macro definition replaces a single identifier with the result of a specified function.
The following line defines the macro SUM as having two parameters a and b and the replacement tokens (a + b):
#define SUM(a,b) (a + b)
This definition would cause the preprocessor to change the following statements (if the statements appear after the previous definition):
c = SUM(x,y); c = d * SUM(x,y);
In the output of the preprocessor, these statements would appear as:
c = (x + y); c = d * (x + y);
Use parentheses to ensure correct evaluation of replacement text. For example, the definition:
#define SQR(c) ((c) * (c))
requires parentheses around each parameter c in the definition in order to correctly evaluate an expression like:
y = SQR(a + b);
The preprocessor expands this statement to:
y = ((a + b) * (a + b));
Without parentheses in the definition, the correct order of evaluation is not preserved, and the preprocessor output is:
y = (a + b * a + b);
Arguments of the # and ## operators are converted before replacement of parameters in a function-like macro.
The number of arguments in a macro invocation must be the same as the number of parameters in the corresponding macro definition.
Commas in the macro invocation argument list do not act as argument separators when they are:
Once defined, a preprocessor identifier remains defined and in scope independent of the scoping rules of the language. The scope of a macro definition begins at the definition and does not end until a corresponding undef directive is encountered. If there is no corresponding undef directive, the scope of the macro definition lasts until the end of the compilation unit.
A recursive macro is not fully expanded. For example, the definition
#define x(a,b) x(a+1,b+1) + 4
expands
x(20,10)
to
x(20+1,10+1) + 4
rather than trying to expand the macro x over and over within itself. After the macro x is expanded, it is a call to function x().
A definition is not required to specify replacement tokens. The following definition removes all instances of the token debug from subsequent lines in the current file:
#define debug
You can change the definition of a defined identifier or macro with a second preprocessor define directive only if the second preprocessor define directive is preceded by a preprocessor undef directive. The undef directive nullifies the first definition so that the same identifier can be used in a redefinition.
Within the text of the program, the preprocessor does not scan character constants or string constants for macro invocations.
The following program contains two macro definitions and a macro invocation that refers to both of the defined macros:
/** ** This example illustrates #define directives. **/ #include <stdio.h> #define SQR(s) ((s) * (s)) #define PRNT(a,b) \ printf("value 1 = %d\n", a); \ printf("value 2 = %d\n", b) ; int main(void) { int x = 2; int y = 3; PRNT(SQR(x),y); return(0); }
After being interpreted by the preprocessor, this program is replaced by code equivalent to the following:
#include <stdio.h> int main(void) { int x = 2; int y = 3; printf("value 1 = %d\n", ( (x) * (x) ) ); printf("value 2 = %d\n", y); return(0); }
The program produces the following output:
+--------------------------------------------------------------------------------+ |value 1 = 4 | |value 2 = 3 | +--------------------------------------------------------------------------------+
(C) Copyright IBM Corporation 1992, 2006. All Rights Reserved.