Q. Can include files be nested?
Yes. Include files can be nested any number of times. As long as you use precautionary measures, you can avoid including the same file twice. In the past, nesting header files was seen as bad programming practice, because it complicates the dependency tracking function of the MAKE program and thus slows down compilation. Many of today's popular compilers make up for this difficulty by implementing a concept called precompiled headers, in which all headers and associated dependencies are stored in a precompiled state.
Many programmers like to create a custom header file that has #include statements for every header needed for each module. This is perfectly acceptable and can help avoid potential problems relating to #include files, such as accidentally omitting an #include file in a module.
Q. How many levels deep can include files be nested?
Even though there is no limit to the number of levels of nested include files you can have, your compiler might run out of stack space while trying to include an inordinately high number of files. This number varies according to your hardware configuration and possibly your compiler.
In practice, although nesting include files is perfectly legal, you should avoid getting nest-crazy and purposely implementing a large number of include levels. You should create an include level only where it makes sense, such as creating one include file that has an #include statement for each header required by the module you are working with.
Q. What is the concatenation operator?
The concatenation operator (##) is used to concatenate (combine) two separate strings into one single string. The concatenation operator is often used in C macros, as the following program demonstrates:
#include <stdio.h>
#define SORT(x) sort_function ## x
voidmain(
void);
voidmain(
void)
{
char
* array;
int
elements, element_size;
...
SORT(
3)(array, elements, element_size);
...
}
In the preceding example, the SORT macro uses the concatenation operator to combine the strings sort_function and whatever is passed in the parameter x. This means that the line
SORT(3)(array, elements, element_size);
is run through the preprocessor and is translated into the following line:
sort_function3(array, elements, element_size);
As you can see, the concatenation operator can come in handy when you do not know what function to call until runtime. Using the concatenation operator, you can dynamically construct the name of the function you want to call, as was done with the SORT macro.
Q. How can type-insensitive macros be created?
A type-insensitive macro is a macro that performs the same basic operation on different data types. This task can be accomplished by using the concatenation operator to create a call to a type-sensitive function based on the parameter passed to the macro. The following program provides an example:
#include <stdio.h>
#define SORT(data_type) sort_ ## data_type
voidsort_int(
int** i);
voidsort_long(
long** l);
voidsort_float(
float** f);
voidsort_string(
char** s);
voidmain(
void);
voidmain(
void)
{
int
** ip;
long
** lp;
float
** fp;
char
** cp;
...
sort(
int)(ip);
sort(
long)(lp);
sort(
float)(fp);
sort(
char)(cp);
...
}
This program contains four functions to sort four different data types: int, long, float, and string (notice that only the function prototypes are included for brevity). A macro named SORT was created to take the data type passed to the macro and combine it with the sort_ string to form a valid function call that is appropriate for the data type being sorted. Thus, the string
sort(int)(ip);
translates into
sort_int(ip);
after being run through the preprocessor.
No comments:
Post a Comment