⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macro.gml

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 GML
字号:
.pp
A directive of the form,
.ppix #define
.cillust begin
.mono #define
identifier replacement-list
.cillust end
.pc
defines a
.ix 'macro' 'defining'
.us macro
with the name
.us identifier.
This particular form of macro is called an
.ix 'macro' 'object-like'
.us object-like
macro, because it is used like an object (as opposed to a function).
Any source line that contains a token matching the macro name has
that token replaced by the
.us replacement-list.
The tokens of the replacement-list are then rescanned for more
macro replacements.
.pp
For example, the macro,
.millust #define TABLE_LIMIT 256
defines the macro
.mono TABLE_LIMIT
to be equivalent to the token
.mono 256.
This is sometimes called a
.ix 'manifest constant'
.ix constant manifest
.ix constant '#define'
.ix constant 'enumeration'
.us manifest constant,
because it provides
a descriptive term for a value that makes programs easier to
read.
It is a very good idea to use descriptive names wherever appropriate
to improve the readability of a program.
It may also save time if the same value is used many different places,
and the value must be changed at some point.
.pp
Care must be exercised when using more complicated object-like macros.
Consider the following example:
.millust begin
#define COUNT1 10
#define COUNT2 20
#define TOTAL_COUNT COUNT1+COUNT2
/* ... */
memptr = malloc( TOTAL_COUNT * sizeof( int ) );
.millust end
.pc
If
.kw int
is 2 bytes in size,
this call to
.libfn malloc
will allocate 50 bytes of memory, instead of the expected 60.
This occurs because
.mono TOTAL_COUNT&SYSRB.*&SYSRB.sizeof(&SYSRB.int&SYSRB.)
becomes
.mono 10+20&SYSRB.*&SYSRB.2
after macro replacement, and the precedence rules for expression
evaluation cause the multiply to be done first. To solve this
problem, the macro for
.mono TOTAL_COUNT
should be defined as:
.millust #define TOTAL_COUNT (COUNT1+COUNT2)
.pp
A directive of the form,
.ppix #define
.cillust begin
.kwpp #define
identifier
..ct .mono (
identifier-list
.mono )
replacement-list
.cillust end
.pc
is called a
.ix 'macro' 'function-like'
.us function-like
macro, because it is used like a function call.
No space may appear between
.us identifier
and the left parenthesis in the macro definition.
Any source line(s) that contains what looks like a function call, where
the name of the function matches a function-like macro name, and the
number of parameters matches the number of identifiers in the
.us identifier-list,
has the entire function call replaced by the
.us replacement-list,
substituting the actual arguments of the function call for the
occurrences of the identifiers in the replacement-list.
If the left parenthesis following the macro name was created
as the result of a macro substitution, no further substitution will
take place.
If the macro name appears but is not followed by a left parenthesis,
no further substitution will take place.
.keep begin
:P.
Consider this example:
.millust begin
#define endof( string ) \
    (string + strlen( string ))
.millust end
.keep end
.pc
The
.mono \
causes the two lines to be joined together into one logical
line, making this equivalent to,
.millust #define endof( string )    (string + strlen( string ))
The function-like macro
.mono endof
can be used to find a pointer to the null character terminating
a string. The statement,
.millust begin
endptr = endof( ptr );
.millust end
.pc
will have the macro replaced, so it will then be parsed as,
.millust begin
endptr = (ptr + strlen( ptr ));
.millust end
.pp
Note that, in this case, the argument is evaluated twice. If
.mono StrFn(&SYSRB.ptr&SYSRB.)
was specified instead of
.mono ptr
..ct ,
then the function would get called twice, because the substitution
would yield,
.millust begin
endptr = (StrFn( ptr ) + strlen( StrFn( ptr ) ));
.millust end
.pp
In gathering up the tokens used to identify the arguments,
each sequence of tokens separated by a comma constitutes an
argument, unless that comma happens to be within a matched pair of
left and right parentheses. When a right parenthesis is found that
matches the beginning left parenthesis, and the number of arguments
matches the number of identifiers in the macro definition, then
the gathering of the arguments is complete and the substitution
takes place.
.pp
For example,
.millust begin
#define mymemcpy( dest, src, len ) \
    memcpy( dest, src, len )
/* ... */
mymemcpy( destptr, srcptr, (t=0, t=strlen(srcptr)) );
.millust end
.pc
will, for the parameters
.mono dest
..ct ,
.mono src
and
.mono len
..ct ,
use the arguments
.mono destptr
..ct ,
.mono srcptr
and
.monoon
(t=0, t=strlen(srcptr))
.monooff
respectively.
.pp
This form of macro is also useful for
.ix 'commenting out'
"commenting out" a function
call that is used for debugging the program. For example,
.millust begin
#define alive( where ) printf( "Alive at" where "\n" )
.millust end
.pc
could later be replaced by,
.millust #define alive( where ) /* */
Alternatively, the definition,
.millust #define alive( where )
may be used.
When the module or program is recompiled using this new definition for
.mono alive
..ct ,
all of the calls to
.libfn printf
made as a result of the macro replacement will disappear, without
the necessity of deleting the appropriate lines in each module.
.pp
A directive of the form,
.ppix #undef
.ix 'undefining a macro'
.ix 'macro' 'undefining'
.cillust begin
.kwpp #undef
identifier
.cillust end
.pc
causes the macro definition
for
.us identifier
to be thrown away. No error is reported if no macro definition for
.us identifier
exists.
.*
.section Argument Substitution
.*
.pp
The argument substitution capabilities of
the C preprocessor are very powerful, but
can be tricky. The following sections illustrate the capabilities,
and try to shed light on the problems that might be encountered.
.beglevel
.*
.section Converting An Argument to a String
.*
.pp
In the replacement-string for a function-like macro, each occurrence of
.ix 'preprocessor directive' '#define' '# operator'
.mono #
must be followed by a parameter to the macro. If so, both the
.mono #
and the parameter are replaced by a string created from the characters
of the argument itself, with no
further substitutions performed on the argument.
Each white space within the argument
is converted to a single blank character.
If the argument contains a character constant or string literal, any
occurrences of
.mono "
(double-quote) are replaced by
.mono \"
..ct , and any
occurrences of
.mono \
(backslash) are replaced by
.mono \\
..ct ..li .
.pp
The following table gives a number of examples of the result of the
application of the macro,
.millust #define string( parm ) # parm
as shown in the first column:
..sk 1 c
.if &e'&nobox eq 0 .do begin
.boxdef
..if '&format' eq '7x9' ..th ..do begin
.  .boxcol 19
.  .boxcol 15
..do end
..el ..do begin
.  .boxcol 23
.  .boxcol 19
..do end
.boxbeg
汚rgument             汚fter Substitution
.boxline
.monoon
泂tring( abc )        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -