C Programming - Preprocessors

21.
What is a pragma?

The #pragma preprocessor directive allows each compiler to implement compiler-specific features that can be turned on and off with the #pragma statement. For instance, your compiler might support a feature called loop optimization. This feature can be invoked as a command-line option or as a #pragma directive. To implement this option using the #pragma directive, you would put the following line into your code:

#pragma loop_opt(on)

Conversely, you can turn off loop optimization by inserting the following line into your code:

#pragma loop_opt(off)

Sometimes you might have a certain function that causes your compiler to produce a warning such as Parameter xxx is never used in function yyy or some other warning that you are well aware of but choose to ignore. You can temporarily disable this warning message on some compilers by using a #pragma directive to turn off the warning message before the function and use another #pragma directive to turn it back on after the function. For instance, consider the following example, in which the function named insert_record() generates a warning message that has the unique ID of 100. You can temporarily disable this warning as shown here:

#pragma warn -100    /* Turn off the warning message for warning #100 */
int insert_record(REC* r)   /* Body of the function insert_record() */
{
    /* insert_rec() function statements go here... */
}
#pragma warn +100 /* Turn the warning message for warning #100 back on */

Check your compiler's documentation for a list of #pragma directives. As stated earlier, each compiler's implementation of this feature is different, and what works on one compiler almost certainly won't work on another. Nevertheless, the #pragma directives can come in very handy when you're turning on and off some of your compiler's favorite (or most annoying) features.


22.
What is #line used for?

The #line preprocessor directive is used to reset the values of the __LINE__ and __FILE__ symbols, respectively. This directive is commonly used in fourth-generation languages that generate C language source files. For instance, if you are using a fourth-generation language named "X," the 4GL compiler will generate C source code routines for compilation based on your 4GL source code. If errors are present in your 4GL code, they can be mapped back to your 4GL source code by using the #line directive. The 4GL code generator simply inserts a line like this into the generated C source:

#line 752, "XSOURCE.X"
void generated_code(void)
{
...
}

Now, if an error is detected anywhere in the generated_code() function, it can be mapped back to the original 4GL source file named XSOURCE.X. This way, the 4GL compiler can report the 4GL source code line that has the error in it.

When the #line directive is used, the __LINE__ symbol is reset to the first argument after the #line keyword (in the preceding example, 752), and the __FILE__ symbol is reset to the second argument after the #line keyword (in the preceding example, "XSOURCE.X"). All references hereafter to the __LINE__ and __FILE__ symbols will reflect the reset values and not the original values of __LINE__ and __FILE__.


23.
What are the __DATE__ and __TIME__ preprocessor commands?

The __DATE__ macro is used to insert the current compilation date in the form "mm dd yyyy" into your program. Similarly, the __TIME__ macro is used to insert the current compilation time in the form "hh:mm:ss" into your program. This date-and-time-stamp feature should not be confused with the current system date and time. Rather, these two macros enable you to keep track of the date and time your program was last compiled. This feature can come in very handy when you are trying to track different versions of your program. For instance, many programmers like to put a function in their programs that gives compilation information as to when the current module was compiled. This task can be performed as shown here:

#include <stdio.h>
void main(void);
void print_version_info(void);
void main(void)
{
print_version_info();
}
void print_version_info(void)
{
     printf("Date Compiled: %s\n", __DATE__);
     printf("Time Compiled: %s\n", __TIME__);
}

In this example, the function print_version_info() is used to show the date and time stamp of the last time this module was compiled.


24.
How can you be sure that a program follows the ANSI C standard?

The ANSI C standard provides a predefined symbol named __STDC__ that is set to 1 when the compiler is enforcing strict ANSI standard conformance. If you want your programs to be 100 percent ANSI conformant, you should ensure that the __STDC__ symbol is defined. If the program is being compiled with non-ANSI options, the __STDC__ symbol is undefined. The following code segment shows how this symbol can be checked:


#ifdef __STDC__
     printf("Congratulations! You are conforming perfectly to the ANSI
             standards!\n");
#else
     printf("Shame on you, you nonconformist anti-ANSI rabble-rousing programmer!\n");
#endif