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

Advanced C 1992

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

Pointers and Indirection

C C C

 

C3C

 

C C C

 

C

In Listing 3.9, RAGSTR.C shows a different way of allocating the strings. In this program, C has been told to allocate an array of string pointers, and then give constants as initializers. This technique wastes no space, and with two allocated arrays (one is the pointer to a string array, and the other is the string array that’s being pointed to), only 521 bytes of storage are required.

Listing 3.9. RAGSTR.C.

/* RAGSTR, written 20 May 1992 by Peter D. Hipson */

/* Non-fixed-length

strings in a program. */

#include

<stdio.h>

// Make includes first part of file

#include

<string.h>

// For string functions.

int main(void); // Define main() and the fact that this program doesn’t

 

// use any passed parameters.

int main()

{

 

int

i;

char

*szSaying[] =

{

“Firestone’s Law of Forecasting:”,

Chicken Little only has to be right once.”, “”, “”,

“Manly’s Maxim:”,

Logic is a systematic method of coming to”,

the wrong conclusion with confidence.”,

“”,

“”,

“Moer’s truism:”,

The trouble with most jobs is the job holder’s”,

resemblance to being one of a sled dog team. No one”,

gets a change of scenery except the lead dog.”,

“”,

continues

95

Part I • Honing Your C Skills

Listing 3.9. continued

“”,

“Cannon’s Comment:”,

If you tell the boss you were late for work because you”,

had a flat tire, the next morning you will have a flat tire.”

};

 

printf(

 

“Number of lines is %d\n”

 

“size of item is %d\n”

 

“size of (char) is %d\n”,

 

sizeof(szSaying) / sizeof(szSaying[0]),

// Number of elements.

sizeof(szSaying[0]),

// Size of char *

sizeof(szSaying[0][0]));

// Size of char

switch (sizeof(char *))

 

{

 

case 2: // Near pointers

 

printf(“Addr len saying\n”);

 

break;

 

case 4: // Far pointers, 808x segmented pointers. printf(“Address len saying\n”);

break;

}

for (i = 0; i < (sizeof(szSaying) / sizeof(szSaying[0])); i++)

{

printf(“%p %3d ‘%s’\n”, szSaying[i], strlen(szSaying[i]), szSaying[i]);

}

return (0);

}

Notice that the main body of the program, especially the for() loop used to print the strings, is identical in each program, despite the fact that each program has two different types of array addressing.

96

Pointers and Indirection

C C C

 

C3C

 

C C C

 

C

Figure 3.3 shows an example of how the memory for RAGSTR.C’s szSaying is allocated and used. In this program, szSaying is a single-dimensional array of character pointers. Each pointer then is initialized to point to the correct initializing character string.

Figure 3.3. szSaying in RAGSTR.C.

Don’t be concerned if this discussion leaves you confused—certain parts of the C language, and the way it is used, can confuse anyone. The important factors in the preceding two programs include the following:

1.A two-dimensional array of type char, accessed with only one subscript, effectively returns a pointer to a character string.

2.A single-dimensional array of type char * can be initialized with a set of string constants.

3.If a single-dimensional array of type char * is initialized with a set of string constants, you should be careful about modifying them. The process of modifying a string constant is undefined under ANSI C, and many compilers keep only one copy of a set of identical strings (also legitimate under ANSI C).

4.A single-dimensional array of type char *, initialized with a set of string constants, uses less memory than a two-dimensional array of type char.

97

Part I • Honing Your C Skills

5.A two-dimensional array of type char can be initialized and effectively modified by a program.

When you are working under the constraint that character strings stored in a ragged-right format are difficult—if not impossible—to modify, this format can save a large amount of wasted storage space.

Summary

In this chapter, you learned about pointers and indirection.

Pointers are generally variables whose contents are the address of a memory object.

Indirection is the modification of the memory object pointed to by a pointer.

Strings are arrays of type char. The end of a string is indicated by the NULL character.

Indirection is used often in functions that must modify one (or more) of the parameters that was passed to the function.

Strings are best protected by good programming style: Be sure all buffers and string variables can hold the objects placed in them.

Strings can be stored in a ragged-right format that saves memory. Generally, such strings are difficult to modify.

98

CSpecial PointersCand Their Use CC C C

C4C C

4 C C C

C C C

C C C

Special Pointers and

Their Use

Chapters 2 and 3 described pointers as they pertain to data objects. This chapter discusses pointers that point to objects other than data. Just as you can have a pointer that points to a data object, you can also have a pointer that points to a function. Pointers have several special uses in programming, too. One such use is to obtain the program’s name and any parameters that have been entered by the user and passed to the program by the operating system.

Command Line Arguments

Command line arguments are vital to many programs you create. Command line arguments are used for options, input and output data sources, and to enable the user to pass parameters to the program.

99

Part I • Honing Your C Skills

The operating system processes the arguments the user enters, and places each one in a string that is pointed to by a pointer that you can access. Suppose that the user enters the following command line:

WONDER /Why Ask.dat

The program can access not only the program’s name, but also the command line arguments. These are passed to the main() function as parameters. Until now, the main() function has taken no parameters; in reality, however, three parameters are passed to main() when it is called. The function prototype for the main() function is

int main(

int argc, char *argv[], char *envp[]

)

The argc parameter, an integer, contains the number of elements in the passed array of argv[]. Because the first member of argv[] is the program’s name (usually this is a fully qualified name, complete with the drive and directory information), the value of argc is always at least 1. Some compilers and operating systems don’t provide the program name, but have argv[0] point instead to some predefined string constant, such as "C".

The * argv[] parameter is an array of char pointers. The first element in argv[] always points to the program’s name, and each subsequent member points to a parameter. Each parameter is separated by the operating system’s default parameter separator, usually a blank or comma. Under the PC’s DOS operating system, only a blank is used as a separator. The end of this list of parameters can be determined by either using argc or testing the pointer, which is NULL to signify the end of the list.

The * envp[] parameter is an array of char pointers. The first element in argv[] points to the first environment string (when you are using DOS on the PC). Each subsequent member points to a succeeding environment string. Each environment string looks just like it does when you enter the DOS command SET, where you have an environment variable, an equal sign, and a string. The end of this list of environment strings can be determined by testing each envp[] pointer, when NULL is encountered, signifying the end of the environment list.

Listing 4.1 is a simple program that prints both the passed parameters and the environment strings to the screen. This program’s output depends somewhat on which operating system it runs; however, it shouldn’t fail when it is run under different operating systems.

100

Special Pointers and Their Use

C C C

 

C4C

 

C C C

 

C

Listing 4.1. MAINARGS.C.

/* MAINARGS, written 22 May 1992 by Peter D. Hipson */ /* This program prints a program's arguments. */

#include <stdio.h> // Make includes first part of file #include <string.h> // For string functions.

int main(

// Define main() and the fact that this program uses

int

argc, // the passed parameters.

char

*argv[],

char

*envp[]

);

 

int main(

 

int

argc,

char

*argv[],

char

*envp[]

)

 

{

 

int i;

printf("\n");

printf("Program name is '%s'\n\n", argv[0]);

//argc includes the program name, so decrement for actual

//passed parameters.

printf("Number of parameters %d \n\n", argc - 1);

//It's just as valid is to use:

//for (i = 1; i < argc; i++)

for (i = 1; argv[i]; i++)

continues

101

Part I • Honing Your C Skills

Listing 4.1. continued

{

printf("Passed parameter %2d is '%.50s'\n", i,

argv[i]);

}

printf("\n");

//Environment variables may not be meaningful for all

//operating systems. Check the compiler's documentation.

//If this information is not available on your system,

//delete the below for() loop.

for (i = 0; envp[i]; i++)

{

printf("Environment string %2d is '%.50s'\n", i,

envp[i]);

}

return (0);

}

As the MAINARGS program shows, the command line parameters are easy to access—the operating system does all the work for you. Almost all the work, at least. You still have to process the arguments and do whatever is required of your program.

Programs generally accepts three types of information:

1.Input or output filenames

2.Options, generally preceded by either a hyphen (-) or a slash (/)

3.Parameters, which may or may not be in any given format

Let’s write a program that expects two filenames (both input and output), several options, and a parameter. This program reformats the lines of the input to the number of characters specified by the parameter. Possible options are to justify the lines or make them flush left or flush right. For simplicity, you don’t write the program to actually do this work; however, you process the program’s command line, and set flags, filenames, and the line width. Listing 4.2, JUSTIFY.C, is the basis for this program.

102

Special Pointers and Their Use

C C C

 

C4C

 

C C C

 

C

Listing 4.2. JUSTIFY.C.

/* JUSTIFY, written 22 May 1992 by Peter D. Hipson */

/* This program justifies text files (shell only). It assumes

*and uses Microsoft's extensions to C. Readers with other

*compilers may have to change the program to use the calls

*that their compiler supplies to perform the same functions. */

/* This program assumes the command line syntax shown in * the GiveHelp() function. */

#include

<stdio.h>

// Make includes first part of file

#include

<string.h>

// For string functions.

#include

<stdlib.h>

// Standard include items.

#include

<process.h>

// For exit() etc.

#define

LEFT

1

 

#define

RIGHT

2

 

#define

JUSTIFY

3

 

#define

INNAME

1

 

#define

OUTNAME

2

 

#define

WIDTH

3

 

#define

LAST_THING 4

 

#define

ARG_LEFT

 

'l'

#define

ARG_RIGHT

'r'

#define

ARG_JUSTIFY

'j'

#define

ARG_SLASH

'/'

#define

ARG_DASH

 

'-'

#define

ARG_HELP

 

'?'

#define

NOINNAME

 

1

#define

NOOUTNAME

2

#define

BAD_WIDTH

3

#define

BAD_PARM

 

4

#define

BAD_OPTION

5

#define

NAME_MISSING

6

continues

103

Part I • Honing Your C Skills

Listing 4.2. continued

int main(

// Define main() and the fact that this program uses

int

argc,

// the passed parameters.

char

*argv[],

 

 

char

*envp[]

 

 

);

 

 

 

void

GiveHelp(

 

 

int

nLevel,

 

 

char

*psItem);

 

int main(

 

 

int

argc,

 

 

char

*argv[],

 

 

char

*envp[]

 

 

)

 

 

 

{

 

 

 

char

*pszTemp;

 

 

char

szBuffer[129];

// Temporary work buffer.

char

szProgram[30];

 

char

szInputFile[132];

// Make large enough for your OS.

char

szOutputFile[132]; // Make large enough for your OS.

/* strings for _splitpath() (which parses a filename) */

char

szDrive[_MAX_DRIVE];

char

szDir[_MAX_DIR];

 

char

szFname[_MAX_FNAME];

char

szExt[_MAX_EXT];

 

int

i;

 

 

int

j;

 

 

int

nCurrentParameter = INNAME;

int

nTempWidth = 0;

 

int

nLineWidth = 80;

 

int

nJustification = LEFT;

104