|
||
Preprocessing Directives
|
||||||||||||||||||||||||||||||||||
The table below shows the preprocessor commands and operators that are supported in SilverC. These are further explained in sections that follow.
|
||||||||||||||||||||||||||||||||||
The #include directive is used to cause C source to be read in and inserted at that point in the compilation. Standard C defines three forms of #include ; SilverC implements only the first two:
Note that the SilverC compiler does not distinguish between the "" form and the <> form in terms of the places where it searches for files.
|
||||||||||||||||||||||||||||||||||
Predefined Macros SilverC predefines the following macros before beginning compilation:
These macros are not allowed to be modified (as by #undef , #define sequences). All of them but __FILE__ and __LINE__ remain constant during compilation; __FILE__ and __LINE__ are not true constants, since they change as compilation proceeds. Both may be affected by use of the #line directive. |
||||||||||||||||||||||||||||||||||
Stringizing The SilverC preprocessor supports the # operator (the 'stringize' operator), which is used to convert macro parameters into strings. An occurrence of # in a macro definition, followed by the name of a macro formal parameter causes the # and the parameter to be replaced by the corresponding actual argument, enclosed in quotation marks. Each sequence whitespace that occurs in the expansion of the formal parameter is replaced by a single space. Embedded quotation or backslash characters are preserved.
It is an error for the # operator to occur without being followed by the name of a macro formal parameter.
An example:
#define Stringize(x) # x ... char msg[60];
strcpy( msg, Stringize( 1 + 2 = 3 ) );
The array msg now contains the string "1 + 2 = 3".
|
||||||||||||||||||||||||||||||||||
Token Pasting The SilverC preprocessor supports the ## operator (the 'token pasting' operator), which is used to combine the two tokens surrounding the ## operator into a single token. This process may yield an invalid token, in which case, a compile error will be generated.
It is an error for the ## operator to occur without being preceded and followed valid C tokens.
An example:
#define MAKE_HANDLE(name) typedef struct name##_t { int dummy; } *name MAKE_HANDLE(Screen); MAKE_HANDLE(Window);
void DestroyScreen( Screen *screen ) { ... }
void DestroyWindow( Window *window ) { ... }
Traditionally in C, ints or void pointers (void *) are used to implement handles. The drawback to this approach is that handles to differing types are indistinguishable, opening the door to type violations undetectable by the compiler.
In this example, the macro MAKE_HANDLE uses the token pasting facility to fabricate unique types based on a dummy structure; the handles are pointers to these types. These pointers are type-safe in that the compiler can distinguish between them in calls and assignments. The effect of the two uses of MAKE_HANDLE is as if the following code were written:
typedef struct Screen_t { int dummy; } *Screen; typedef struct Window_t { int dummy; } *Window;
This type of usage gives the compiler a chance to catch such invalid usages.
|
||||||||||||||||||||||||||||||||||
The #line preprocessor directive may be used to cause the compiler to believe that the current line, and possibly the current filename are different than they really are. The syntax is either of:
#line <integer constant> "filename" #line <integer constant>
|
||||||||||||||||||||||||||||||||||
The #error preprocessor directive may be used to force a compiler error to be generated, that is, compilation will not complete successfully. The syntax is as follows:
#error <token sequence>
E088: <filename> <line #>: #error: <token sequence>
For example:
#if ! defined(_SILVERC) #error This must be compiled by SilverC! #endif
|