Data Type Conversions

Chapter 14 - Advanced Programming Topics

Visual C++ 6: The Complete Reference
Chris H. Pappas and William H. Murray, III
  Copyright 1998 The McGraw-Hill Companies

Advanced Preprocessor Statements
There are actually 12 standard preprocessor statements, sometimes referred to as directives, shown in the following listing:
#define
#else
#elif
#endif
#error
#if
#ifdef
#ifndef
#include
#line
#pragma
#undef
You are already familiar with two of them, #include, and #define.
Recall that the preprocessor processes a source file before the compiler translates the program into object code. By carefully selecting the correct directives, you can create more efficient header files, solve unique programming problems, and prevent combined files from crashing in on your declarations.
The following sections explain the unique function of each of the ten new preprocessor directives not previously discussed. Some of the examples will use the code found in STDIO.H to illustrate the construction of header files.
#ifdef and #endif Directives
The #ifdef and #endif directives are two of several conditional preprocessor statements. They can be used to selectively include certain statements in your program. The #endif directive is used with all of the conditional preprocessor statements to signify the end of the conditional block. For example, if the name LARGE_CLASSES has been previously defined, the following code segment will define a new name called MAX_SEATS:
#ifdef LARGE_CLASSES
#define MAX_SEATS 100
#endif
Whenever a C++ program uses standard C functions, use the #ifdef directive to modify the function declarations so that they have the required extern “C” linkage, which inhibits the encoding of the function name. This usually calls for the following pair of directive code segments to encapsulate the translated code:
/*  used in GRAPH.H  */

#ifdef __cplusplus
extern “C” {         /* allow use with C++ */
#endif

/* translation units */

#ifdef __cplusplus
}
#endif
#undef Directive
The #undef directive tells the preprocessor to cancel any previous definition of the specified identifier. This next example combines your understanding of #ifdef with the use of #undef to change the dimension of MAX_SEATS:
#ifdef LARGE_CLASSES
#undef MAX_SEATS 30
#define MAX_SEATS 100
#endif
The compiler will not complain if you try to undefine a name not previously defined. Notice that once a name has been undefined, it may be given a completely new definition with another #define directive.
#ifndef Directive
Undoubtedly, you are beginning to understand how the conditional directives operate. The #ifndef preprocessor checks to see if the specified identifier does not exist, and then performs some action. The code segment that follows is taken directly from STDIO.H:
#ifndef _SIZE_T_DEFINED
typedef unsigned int size_t;
#define _SIZE_T_DEFINED
#endif
In this case, the conditionally executed statements include both a typedef and #define preprocessor. This code takes care of defining the type size_t, specified by the ANSI C committee as the return type for the operator sizeof( ). Make sure that you read the section titled “Proper Use of Header Files” later in this chapter to understand what types of statements can be placed in header files.
#if Directive
The #if preprocessor also recognizes the term defined:
#if defined(LARGE_CLASSES) && !defined (PRIVATE_LESSONS)
#define MAX_SEATS 30
#endif
The code shows how the #if directive, together with the defined construct, accomplishes what would otherwise require an #ifndef nested in an #ifdef:
#ifdef LARGE_CLASSES
#ifndef PRIVATE_LESSONS
#define MAX_SEATS 30
#endif
The two examples produce the same result, but the first is more immediately discerned. Both #ifdef and #ifndef directives are restricted to a single test expression. However, the #if combined with defined allows compound expressions.
#else Directive
The #else directive has the expected use. Suppose a program is going to be run on a VAX computer and a PC operating under DOS. The VAX may allocate 4 bytes, or 32 bits, to the type integer, while the PC may allocate only 2 bytes, or 16 bits. The following code segment uses the #else directive to make certain that an integer is seen the same on both systems:
#ifdef VAX_SYSTEM
#define INTEGER short int
#else
#define INTEGER int
#endif
Of course, the program will have to take care of defining the identifier VAX_SYSTEM when you run it on the VAX. As you can readily see, combinations of preprocessor directives make for interesting solutions.
  Note This type of directive played a major role in the development of Windows applications that were to be source code compatible among Windows 3.x, Windows 95, Windows 98, and Windows NT. Windows 3.2 applications were 16-bit, while Windows 95, Windows 98, and NT applications were essentially 32-bit.
#elif Directive
The #elif directive is an abbreviation for “else if” and provides an alternate approach to nested #if statements. The following code segment checks to see which class size is defined and uniquely defines the BILL macro:
#if defined (LARGE_CLASSES)
     #define BILL printf(“\nCost per student $100.00.\n”)
 #elif defined (PRIVATE_LESSONS)
     #define BILL printf(“\nYour tuition is $1000.00.\n”)
   #else
     #define BILL printf(“\nCost per student $150.00.\n”)
#endif
Notice that the preprocessors don’t have to start in column 1. The ability to indent preprocessor statements for readability is only one of the many useful recommendations made by the ANSI C committee and adopted by Visual C++.
#line Directive
The #line directive overrides the compiler’s automatic line numbering. You can use it to help in debugging your program. Suppose that you have just merged a 50-line routine into a file of over 400 statements. All you care about are any errors that could be generated within the merged code.
Normally, the compiler starts line numbering from the beginning of the file. If your routine had an error, the compiler would print a message with a line number of, say, 289. From your merged files point of view, where is that?
However, if you include a #line directive in the beginning of your freshly merged subroutine, the compiler would give you a line error number relative to the beginning of the function:
#line 1
int imy_mergefunction(void)
{
    .
    .
    .
}
#error Directive
The #error directive instructs the compiler to generate a user-defined error message. It can be used to extend the compiler’s own error-detection and message capabilities. After the compiler encounters an #error directive, it scans the rest of the program for syntax errors but does not produce an object file. For example:
#if !defined( _CHAR_UNSIGNED )
#error /J option required.
#endif
This code prints a warning message if _CHAR_UNSIGNED is undefined.
#pragma Directive
The #pragma directive gives the compiler implementation-specific instructions. The Visual C++ compiler supports the pragmas shown in the following list:
alloc_text
auto_inline
check_pointer
check_stack
code_seg
comment
data_seg
function
hdrstop
init_seg
inline_depth
inline_recursion
intrinsic
linesize
loop_opt
message
native_caller
optimize
pack
pagesize
skip
subtitle
title
warning

Books24x7.com, Inc 2000 –  


Visual C++ 6(c) The Complete Reference
Visual Studio 6: The Complete Reference
ISBN: B00007FYGA
EAN: N/A
Year: 1998
Pages: 207

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net