18. How can a program be made to print the line number where an error occurs?
The ANSI C standard includes a predefined macro named __LINE__ that can be used to insert the current source code line number in your program. This can be a very valuable macro when it comes to debugging your program and checking for logic errors. For instance, consider the following portion of code:
int print_document(char* doc_name, int destination)
{
switch (destination)
{
case TO_FILE:
print_to_file(doc_name);
break;
case TO_SCREEN:
print_preview(doc_name);
break;
case TO_PRINTER:
print_to_printer(doc_name);
break;
default:
printf("Logic error on line number %d!\n", __LINE__);
exit(1);
}
}
If the function named print_document() is passed an erroneous argument for the destination parameter (something other than TO_FILE, TO_SCREEN, and TO_PRINTER), the default case in the switch statement traps this logic error and prints the line number in which it occurred. This capability can be a tremendous help when you are trying to debug your program and track down what could be a very bad logic error.
19. How can a program be made to print the name of a source file where an error occurs?
The ANSI C standard includes a predefined macro named __FILE__ that can be used to insert the current source code filename in your program. This macro, like the __LINE__ macro, can be very valuable when it comes to debugging your program and checking for logic errors. For instance, the following code, includes the filename as well as the line number when logic errors are trapped:
int print_document(char* doc_name, int destination)
{
switch (destination)
{
case TO_FILE:
print_to_file(doc_name);
break;
case TO_SCREEN:
print_preview(doc_name);
break;
case TO_PRINTER:
print_to_printer(doc_name);
break;
default:
printf("Logic error on line number %d in the file %s!\n",
__LINE__, __FILE__);
exit(1);
}
}
Now, any erroneous values for the destination parameter can be trapped, and the offending source file and line number can be printed.
20. How can you tell whether a program was compiled using C versus C++?
The ANSI standard for the C language defines a symbol named __cplusplus that is defined only when you are compiling a C++ program. If you are compiling a C program, the __cplusplus symbol is undefined. Therefore, you can check to see whether the C++ compiler has been invoked with the following method:
#ifdef __cplusplus /* Is __cplusplus defined? */
#define USING_C FALSE /* Yes, we are not using C */
#else
#define USING_C TRUE /* No, we are using C */
#endif
When the preprocessor is invoked, it sets USING_C to FALSE if the __cplusplus symbol is defined. Otherwise, if __cplusplus is undefined, it sets USING_C to TRUE. Later in your program, you can check the value of theUSING_C constant to determine whether the C++ compiler is being used.
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 #linekeyword (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
25. How do you override a defined macro?
You can use the #undef preprocessor directive to undefine (override) a previously defined macro. Many programmers like to ensure that their applications are using their own terms when defining symbols such as TRUE and FALSE. Your program can check to see whether these symbols have been defined already, and if they have, you can override them with your own definitions of TRUE and FALSE. The following portion of code shows how this task can be accomplished:
...
#ifdef TRUE /* Check to see if TRUE has been defined yet */
#undef TRUE /* If so, undefine it */
#endif
#define TRUE 1 /* Define TRUE the way we want it defined */
#ifdef FALSE /* Check to see if FALSE has been defined yet */
#undef FALSE /* If so, undefine it */
#endif
#define FALSE !TRUE /* Define FALSE the way we want it defined */
...
In the preceding example, the symbols TRUE and FALSE are checked to see whether they have been defined yet. If so, they are undefined, or overridden, using the #undef preprocessor directive, and they are redefined in the desired manner. If you were to eliminate the #undef statements in the preceding example, the compiler would warn you that you have multiple definitions of the same symbol. By using this technique, you can avoid this warning and ensure that your programs are using valid symbol definitions.
26. How can you check to see whether a symbol is defined?
You can use the #ifdef and #ifndef preprocessor directives to check whether a symbol has been defined (#ifdef) or whether it has not been defined (#ifndef). Many programmers like to ensure that their own version of NULL is defined, not someone else's. This task can be accomplished as shown here:
#ifdef NULL
#undef NULL
#endif
#define NULL (void*) 0
The first line, #ifdef NULL, checks to see whether the NULL symbol has been defined. If so, it is undefined using #undef NULL and the new definition of NULL is defined.
To check whether a symbol has not been defined yet, you would use the #ifndef preprocessor directive.
85 docs|57 tests
|
1. What is the purpose of preprocessors in C programming? |
2. What are the common preprocessor directives in C programming? |
3. What is the difference between #include and #define in C programming? |
4. How are macros expanded in C programming? |
5. Can preprocessor directives be nested in C programming? |
|
Explore Courses for Interview Preparation exam
|