|Access||Adobe photoshop||Algoritmi||Autocad||Baze de date||C||C sharp|
|Calculatoare||Corel draw||Dot net||Excel||Fox pro||Frontpage||Hardware|
|Php||Power point||Retele calculatoare||Sql||Tutorials||Webdesign||Windows|
|Asp||Autocad||C||Dot net||Excel||Fox pro||Html||Java|
Directives are always introduced by a line that starts with a
include a source file
define a macro
undefine a macro
control error reporting
force an error message
used for implementation-dependent control
null directive; no effect
Table 7.1. Preprocessor directives
The meanings and use of these features are described in the following
sections. Make a note that the
This is simple: a plain
There are two ways of defining macros, one of which looks like a function and one which does not. Here is an example of each:#define FMAC(a,b) a here, then b
Both definitions define a macro and some replacement text, which will be used to replace later occurrences of the macro name in the rest of the program. After those definitions, they can be used as follows, with the effect of the macro replacement shown in comments:NONFMAC
For the non-function macro, its name is simply replaced by its replacement
text. The function macro is also replaced by its replacement text; wherever the
replacement text contains an identifier which is the name of one of the macro's
'formal parameters', the actual text given as the argument is used in place of
the identifier in the replacement text. The scope of the names of the formal
parameters is limited to the body of the
For both forms of macro, leading or trailing white space around the replacement text is discarded.
A curious ambiguity arises with macros: how do you define a non-function macro whose replacement text happens to start with the opening parenthesis character (? The answer is simple. If the definition of the macro has a space in front of the (, then it isn't the definition of a function macro, but a simple replacement macro instead. When you use function-like macros, there's no equivalent restriction.
The Standard allows either type of macro to be redefined at any time, using
provided that there isn't any attempt to change the type of the macro and that
the tokens making up both the original definition and the redefinition are
identical in number, ordering, spelling and use of white space. In this context
all white space is considered equal, so this would be correct:
because comment is a form of white space. The token sequence for both cases (w-s stands for a white-space token) is:# w-s define w-s XXX w-s abc w-s def w-s hij w-s
Where will occurrences of the macro name cause the replacement text to be
substituted in its place? Practically anywhere in a program
that the identifier is recognized as a separate token, except as the identifier
and expect the second
#define to be replaced by
#XXX, causing an error.
When the identifier associated with a non-function macro is seen, it is replaced by the macro replacement tokens, then rescanned (see later) for further replacements to make.
Function macros can be used like real functions; white space around the macro name, the argument list and so on, may include the newline character:#define FMAC(a, b) printf('%s %sn', a, b)
The 'arguments' of a function macro can be almost any arbitrary token
sequence. Commas are used to separate the arguments from each other but can be
hidden by enclosing them within parentheses, and
Note very carefully that the parentheses around the second argument to CALL were preserved in the replacement: they were not stripped from the text.
If you want to use macros like
taking a variable number of arguments, the Standard is no help to you. They are
If any argument contains no preprocessor tokens then the behaviour is undefined. The same is true if the sequence of preprocessor tokens that forms the argument would otherwise have been another preprocessor directive:#define CALL(a, b) a b
In our opinion, the second of the erroneous uses of
CALL should result in defined
behaviour-anyone capable of writing that would clearly benefit from the
attentions of a champion weightlifter wielding a heavy leather bullwhip.
When a function macro is being processed, the steps are as follows:
, or followed by
There is special treatment for places in the macro replacement text where
one of the macro formal parameters is found preceded
This example demonstrates the feature:#define MESSAGE(x) printf('Message: %sn', #x)
As an example of token pasting, here is a multi-stage operation, involving rescanning (which is described next).#define REPLACE some replacement text
Once the processing described above has occurred, the replacement text plus the following tokens of the source file is rescanned, looking for more macro names to replace. The one exception is that, within a macro's replacement text, the name of the macro itself is not expanded. Because macro replacement can be nested, it is possible for several macros to be in the process of being replaced at any one point: none of their names is a candidate for further replacement in the 'inner' levels of this process. This allows redefinition of existing functions as macros:#define exit(x) exit((x)+1)
These macro names which were not replaced now become tokens which are immune from future replacement, even if later processing might have meant that they had become available for replacement. This prevents the danger of infinite recursion occurring in the preprocessor. The suppression of replacement is only if the macro name results directly from replacement text, not the other source text of the program. Here is what we mean:#define m(x) m((x)+1)
If that doesn't make your brain hurt, then go and read what the Standard says about it, which will.
There is a subtle problem when using arguments to function macros./* warning - subtle problem in this example */
The formal parameter of
x; the actual argument is
The use of the parentheses should be noticed. The following example is likely to give trouble:/* bad example */
The problem is that the last expression in the second printf is replaced by3*2+2
which results in
so, when formal parameters occur in the replacement
text, you should look carefully at them too. Correct versions of
DOUBLE are these:
Macros have a last little trick to surprise you with, as this shows.#include <stdio.h>
Why is this going to cause problems? Because the replacement text of the
macro refers to
ip gets incremented
twice. Macros should never be used with expressions that involve side effects,
unless you check very carefully that they are safe.
Despite these warnings, they provide a very useful feature, and one which will be used a lot from now on.
The name of any
identifier can be forcibly forgotten by saying
It isn't an error to
a name which isn't currently defined.
This occasionally comes in handy. Chapter points out that some library functions may actually be macros, not functions, but by undefing their names you are guaranteed access to a real function.
This comes in two flavours:#include <filename>
both of which cause a new file to be read at the
point where they occur. It's as if the single line containing the directive is
replaced by the contents of the specified file. If that file contains erroneous
statements, you can reasonably expect that the errors will be reported with a
correct file name and line number. It's the compiler writer's job to get that right.
The Standard specifies that at least eight nested levels of
# include must be supported.
The effect of using brackets
In general, brackets are used when you specify standard library header files, quotes are used for private header files-often specific to one program only.
Although the Standard doesn't define what constitutes a valid file name, it
does specify that there must be an implementation-defined unique way of
translating file names of the form
x represents a
'letter'), into source file names. Distinctions of upper and lower case may be
ignored and the implementation may choose only to use six significant
characters before the '
You can also write this:# define NAME <stdio.h>
to get the same effect as# include <stdio.h>
but it's a rather roundabout way of doing it, and
unfortunately it's subject to implementation defined rules about how the text
> is treated.
It's simpler if the replacement text for
comes out to be a string, for example
There is no problem with implementation defined behaviour here, but the paths searched are different, as explained above.
For the first case, what happens is that the token sequence which replaces NAME is (by the rules already given)<
and for the second case'stdio.h'
The second case is easy, since it's just a string-literal which is a legal token for a
include directive. It is implementation
defined how the first case is treated, and whether or not the sequence of
tokens forms a legal header-name.
Finally, the last character of a file which is being
included must be a plain newline.
Failure to include a file successfully is treated as an error.
The following names are predefined within the preprocessor:
The current source file line number, a decimal integer constant.
The 'name' of the current source code file, a string literal.
The current date, a string literal. The form is
where the month name is as
defined in the library function
and the first digit of the date is a space if the date is less than 10.
The time of the translation; again
a string literal in the form produced by asctime, which has the form
The integer constant 1. This is used to test if the compiler is Standard-conforming, the intention being that it will have different values for different releases of the Standard.
A common way of using these predefined names is the following:#define TEST(x) if(!(x))
If the argument to
gives a false result, the message is printed, including the filename and line
number in the message.
There's only one minor caveat: the use of the
if statement can cause confusion
in a case like this:
The else will get associated with the hidden if generated by expanding the
TEST macro. This is most unlikely to
happen in practice, but will be a thorough pain to track down if it ever does
sneak up on you. It's good style to make the bodies of every control of flow
statement compound anyway; then the problem goes away.
None of the names
or defined may be used in
The Standard specifies that any other reserved names will either start with an underscore followed by an upper case letter or another underscore, so you know that you are free to use any other names for your own purposes (but watch out for additional names reserved in Library header files that you may have included).
This is used to set the value of the built in names
__FILE__. Why do this? Because a lot of tools nowadays actually generate C as their output.
This directive allows them to control the current line number. It is of very
limited interest to the 'ordinary' C programmer.
Its form is# line number optional-string-literal newline
The number sets the value of
the string literal, if present, sets the value of
In fact, the sequence of tokens following
will be macro expanded. After expansion, they are expected to provide a valid
directive of the right form.
A number of the directives control conditional compilation, which allows
certain portions of a program to be selectively compiled or ignored depending
upon specified conditions. The directives concerned are:
together with the preprocessor unary operator defined.
The way that they are used is like this:#ifdef NAME
#endif can be used to test the
definition or otherwise of a given macro name. Of course the
#else can be used with
#elif) too. There is no ambiguity about what a given
#else binds to, because the use of
#endif to delimit the scope of these directives
eliminates any possible ambiguity. The Standard specifies that at least eight
levels of nesting of conditional directives must be supported, but in practice
there is not likely to be any real limit.
These directives are most commonly used to select small fragments of C that are machine specific (when it is not possible to make the whole program completely machine independent), or sometimes to select different algorithms depending on the need to make trade-offs.
#elif constructs take a single integral
constant expression as their arguments. Preprocessor integral constant
expressions are the same as other integral constant expressions except that
they must not contain cast operators. The token sequence that makes up the
constant expression undergoes macro replacement, except that names prefixed by
defined are not expanded. In this context, the expression
defined NAME or
defined ( NAME )
NAME is currently defined,
sizeof can't be used in these
expressions to get the result that you would normally expect.
As with the other conditional statements in C, a resulting value of zero is used to represent 'false', anything else is 'true'.
The preprocessor always must use arithmetic with at least the ranges defined
and treats int expressions as long int and unsigned int as unsigned long int.
Character constants do not necessarily have the same values as they do at
execution time, so for highly portable programs, it's best to avoid using them
in preprocessor expressions. Overall, the rules mean that it is possible to get
arithmetic results from the preprocessor which are different from the results
at run time; although presumably only if the translation and execution are done
on different machines. Here's an example.
It is conceivable that the preprocessor might perform arithmetic with a
greater range than that used in the target environment. In that case, the
might not 'overflow' to give the result of
The following skeleton example illustrates the use of such constants and
also the 'conditional else',
A word of warning. These conditional compilation directives do not obey the same scope rules as the rest of C. They should be used sparingly, unless your program is rapidly to become unreadable. It is impossible to read C when it is laced with these things every few lines. The urge to maim the author of a piece of code becomes very strong when you suddenly come across#else
or whatever immediately visible above. They should be treated like chilli
sauce; essential at times, but more than a tiny sprinkle is too much.
This was the Standard Committee's way of 'opening the back door'. It allows implementation-defined things to take place. If the implementation was not expecting what you wrote (i.e. doesn't recognize it), it is ignored. Here is a possible example:#pragma byte_align
which could be used to tell the implementation that all structure members should be aligned on byte addresses - some processor architectures are able to cope with word-sized structure members aligned on byte addresses, but with a penalty in access speed being incurred.
It could, of course, mean anything else that the implementation chooses it to mean.
If your implementation doesn't have any special meaning for this, then it will have no effect. It will not count as an error.
It will be interesting to see the sort of things that this gets used for.
This directive is followed by one or more tokens at the end of the line. A diagnostic message is produced by the compiler, which includes those tokens, but no further detail is given in the Standard. It might be used like this to abort a compilation on unsuitable hardware:#include <limits.h>
which would be expected to produce some sort of meaningful compilation error and message.
Politica de confidentialitate|
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2023 . All rights reserved
Adauga cod HTML in site