Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Advanced C 1992

.pdf
Скачиваний:
96
Добавлен:
17.08.2013
Размер:
4.28 Mб
Скачать

Part IV • Documenting the Differences

width

Specifies the maximum width.

typelength

The typelength specifier provides information about the size of the object that will receive the input. Using an ‘h’ character specifies a short (16-bit) object while the ‘l’ character specifies a long (32-bit) object.

x

The x type tells scanf() to input an unsigned, hexadecimal integer. This field is affected by the following:

width

Specifies the maximum width.

typelength

The typelength specifier provides information about the size of the object that receives the input. Using an ‘h’ character specifies a short (16-bit) object, while the ‘l’ character specifies a long (32-bit) object.

i

The i type tells scanf() to input a signed decimal integer, which may be in a decimal, octal, or hexadecimal format. The first characters in the string are examined, and if they are 0x, then the number is assumed to be base hexadecimal. If there is a leading 0 with no following x, then the base is assumed to be octal. If the leading character is not a 0, then the number is assumed to be decimal. This field is affected by the following:

width

Specifies the maximum width.

616

ANSI C’s Library Function

C C C

 

14C

 

C C C

 

C C

typelength

The typelength specifier provides information about the size of the object that receives the input. Using an ‘h’ character specifies a short (16-bit) object, while the ‘l’ character specifies a long (32-bit) object.

u

The u type tells scanf() to input an unsigned decimal integer. This field is affected by the following:

width

Specifies the maximum width.

typelength

The typelength specifier provides information about the size of the object that receives the input. Using an ‘h’ character specifies a short (16-bit) object, while the ‘l’ character specifies a long (32-bit) object.

e, f, and g

The e, f, and g types tell scanf() to input a floating point number.

This field is affected by the following:

width

Specifies the maximum width.

typelength

With floating point arguments, the ‘l’ character specifies a long double object (its size being implementation dependent).

617

Part IV • Documenting the Differences

n

The n type tells scanf() to save the current number of characters scanned so far to the variable pointed to by the argument. No modifiers are allowed with the n type.

p

The p and P types tell scanf() to input a pointer. The pointer is scanned in hexadecimal notation, in a format that may be machine dependent. This field is affected by the following:

width

Specifies the maximum width.

typelength

No typelength specifier is used.

s

The s type tells scanf() to input a character string, which consists of a group of nonwhitespace characters. Input is assigned up to the first whitespace character. This field is affected by the following:

width

Specifies the maximum width.

typelength

No typelength specifier is used.

618

ANSI C’s Library Function

C C C

 

14C

 

C C C

 

C C

[...]

The [...] type tells scanf() to input a character string, consisting of all characters that are found in the brackets. Prefixing the characters with a ^ causes all characters that are not in the group to be read.

Typically, this input format is used to read strings that contain blanks or other whitespace characters. This field is affected by the following:

width

Specifies the maximum width.

typelength

No typelength specifier is used.

Summary

This chapter covered the various ANSI standard library functions:

The functions are prototyped in the standard header files.

Programmers must be careful to pass the correct parameters to those functions that take a variable number of arguments (such as printf()) because the compiler cannot check argument types.

About 150 non-ANSI functions are available with many compilers. Using the non-ANSI function may create problems when the program is ported to a different compiler.

619

Part IV • Documenting the Differences

620

CPreprocessorCDirectives CC C C

C15C C

C15C CC C C

C C C

Preprocessor Directives

To help you gain a better understanding of how a C compiler produces the object module, this chapter looks at the process of compiling. Most compilers take the following steps, in this order:

1.Preprocess the input file, in this order:

a.Process the #preprocessor directives.

b.Strip comments from the source (as necessary).

c.Expand all macros.

2.The syntax checker processes the file to check for syntax errors.

3.The code generator generates the necessary object module.

All preprocessor commands begin with a pound symbol (#). It must be the first nonblank character, and for readability, a preprocessor directive should begin in column 1. Notice that a defined identifier is always a macro and can be referred to in that way.

621

Part IV • Documenting the Differences

The C preprocessor offers four operators to help you in creating macros (see the section “The #define Directive”) and the #if series of directives.

The Macro Continuation Operator (\)

A macro usually must be contained on a single line. The macro continuation operator is used to continue a macro that is too long for a single line. When you are breaking a macro over several lines, use the macro continuation operator as the last character in the line to be continued. Here’s an example of a multiline macro:

#define PRINTMSG(operand) \

printf(#operand " = %d\n", operand)

This line is exactly equivalent to the following:

#define PRINTMSG(operand) printf(#operand " = %d\n", operand)

The macro continuation operator allows your macros to be read and formatted more easily. It doesn’t affect the operation of the macro.

The Stringize Operator (#)

The stringize operator is used in creating a macro. It takes the particular operand to the macro and converts it to a string. To see how this works, look at this example:

#define PRINTMSG(operand) printf(#operand " = %d\n", operand)

When an integer variable (nCount) is being used as a counter, for example, you might use the statement to display nCount’s value for debugging:

PRINTMSG(nCount + 1);

This statement then is expanded by the preprocessor to create the following source line:

printf("nCount + 1 " " = %d\n", nCount + 1);

This sample line of code shows that the variable’s name has been included (using string literal concatenation) as part of the format string that printf() uses.

622

Preprocessor Directives

C C C

 

15C

 

C C C

 

C C

The stringize operator causes the particular operand to a macro to be converted to a string, by taking the literal characters of the operand and enclosing them within double quotes.

The Characterize Operator (#@)

The characterize operator, which works much like the stringize operator, is used in creating a macro. It takes a particular single character operand to the macro and converts it to a character literal, by surrounding it with single quotes. To see how this works, look at the following example:

#define MAKECHAR(operand) #@operand

When you want to create a character literal, as part of a case: statement, for example, you can use the MAKECHAR macro:

 

switch(nCount + 1)

 

{

 

case MAKECHAR(A):

/*

Action for capital A */

 

break;

 

case MAKECHAR(B):

/*

Action for capital B */

 

break;

 

default:

 

break;

 

}

The first case statement then is expanded by the Pre-Processor to create the following:

case 'A':

In this sample line of code, the operand has been surrounded by single quotes, yielding a character literal. This example isn’t the most useful for using the characterize operator, but it gets the point across.

The characterize operator causes the particular operand to a macro to be converted to a character literal, by taking the characters of the operand and enclosing them within single quotes. This operator fails if it is given a single quote character.

623

Part IV • Documenting the Differences

The Token Paste Operator (##)

The token paste operator tells the preprocessor to paste, to the token on the other side, the operand that either precedes or follows it. For example, you might code a macro to print one of several variables that have meaningful names:

#define PRINTCOUNTER(variable) \

printf("counter %d is %d", variable, nCounter#variable)

 

This macro definition can then be used in a program such as the following:

int

nCounter1;

int

nCounter2;

int

nCounter3;

int

nCounter4;

PRINTCOUNTER(1);

This call to the macro can be expanded to

printf("variable %d is %d", 1, nCounter1);

You decide how to use this operator. It has many uses when you create macros to help debug programs that use structures heavily.

The Defined Identifier Operator (defined())

The defined() operator is used with the #if and #elif preprocessor commands. This operator returns a logical true (nonzero) value if the identifier used as its operand is currently defined and a logical false (zero) if the operand is not defined.

The primary use for defined() is in testing two different identifiers to see whether they are defined. You can use nested #ifdef statements; using defined(), however, makes the code easier to understand.

624

Preprocessor Directives

C C C

 

15C

 

C C C

 

C C

The #define Directive

The #define command defines macros. C’s macros help you create powerful functionality. Macros can be defined with substitutable parameters or as simple identifiers. The simplest macro probably is the following:

#define TRUE

1

This macro defines the identifier TRUE that always has the numeric value of 1 substituted for it. For example, the following lines have a conditional statement (and some comments):

#define TRUE 1

/* Later in the program... */

 

if (nOurTime

==

TRUE)

 

{/* Process our

time... */

/*

our time

code is here. */

 

}

 

 

After the preprocessor finishes, this simple bit of code then reads:

if (nOurTime == 1)

{

}

This code fragment shows that the preprocessor has substituted the number 1 for the identifier TRUE. In this example, TRUE is the simplest form of a macro—so simple that it usually is referred to as the definition of an identifier. A more complex macro might have one or more operands, which enable you to test and create different statements, such as MACROS (see Listing 15.1).

Listing 15.1. MACROS.C.

/* Program MACROS, written 23 June 1992 by Peter D. Hipson */ /* A program that shows macros. */

#include <stdio.h> #include <stdlib.h>

continues

625