25. How Are Arrays and Pointers Different?

They’re the Same Thing in C

image

This chapter teaches how C’s array and pointer variables share a lot of principles. As a matter of fact, an array is a special kind of pointer. Because of their similarities, you can use pointer notation to get to array values, and you can use array notation to get to pointed-at values.

Perhaps the most important reason to learn how arrays and pointers overlap is for character-string handling. By combining pointer notation (using the dereferencing operation) and array notation (using subscripts), you can store lists of character strings and reference them as easily as you reference array values of other data types.

Also, once you master the heap—a special place in memory that you’ll get an introduction to in the next chapter—you’ll see that pointers are the only way to get to heap memory, where you put data values.

Array Names Are Pointers

An array name is nothing more than a pointer to the first element in that array. The array name is not exactly a pointer variable, though. Array names are known as pointer constants. The following statement defines an integer array and initializes it:

int vals[5] = {10, 20, 30, 40, 50};

You can reference the array by subscript notation. That much you know already. However, C does more than just attach subscripts to the values in memory. C sets up a pointer to the array and names that point to vals. You can never change the contents of vals; it is like a fixed pointer variable whose address is locked in by C. Figure 25.1 shows you what C really does when you define and initialize vals.

Figure 25.1. The array name is a pointer to the first value in the array.

image

Because the array name is a pointer (that can’t be changed), you can print the first value in the array like this:

printf("The first value is %d. ", vals[0]);

But more importantly for this chapter, you can print the first array value like this too:

printf("The first value is %d. ", *vals);

As you’ll see in a moment, this is also equivalent and accesses vals[0]:

printf("The first value is %d. ", *(vals+0));

Warning

image

The fact that an array is a fixed constant pointer is why you can’t put an array name on the left side of an equals sign. You can’t change a constant. (Remember, though, that C relaxes this rule only when you first define the array, because C has yet to fix the array at a specific address.)

Getting Down in the List

Because an array name is nothing more than a pointer to the first value in the array, if you want the second value, you only have to add 1 to the array name and dereference that location. This set of printf() lines

image

does exactly the same as these:

image

If vals is a pointer constant (and it is), and the pointer constant holds a number that is the address to the array’s first element, adding 1 or 2 (or whatever) to vals before dereferencing vals adds 1 or 2 to the address pointed to by vals.

Clue

image

If you’re wondering about the importance of all this mess, hang tight. In a moment you’ll see how C’s pointer notation lets you make C act almost as if it has string variables.

Characters and Pointers

The following two statements set up almost the same thing in memory. The only difference is that in the second statement, pName is a pointer variable, not a pointer constant:

char name[] = "Andrew B. Mayfair";   /* name points to A */
char * pName = "Andrew B. Mayfair";  /* pName points to A */

Because pName is a pointer variable, you can put it on the left side of an equals sign! Therefore, you don’t always have to use strcpy() if you want to assign a character pointer a new string value. The character pointer will only point to the first character in the string. However, %s and all the string functions work with character pointers just as easily as with character arrays (since the two are the same thing) because these functions know to stop at the null zero.

To put a different name in the name array, you have to use strcpy() or assign the string one character at a time, but to make pName point to a different name, you get to do this:

pName = "Theodore M. Brooks";

Clue

image

The only reason string assignment works is that C puts all your program’s string literals into memory somewhere and then replaces them in your program with their addresses. C is not really putting Theodore M. Brooks into pName because pName can hold only addresses. C is putting the address of Theodore M. Brooks into pName.

Note

image

Yea! You now have a way to assign strings new values without using strcpy(). It took a little work to get here, but aren’t you glad you made it? If so, settle down, because there is just one catch (isn’t there always?).

Be Careful with Lengths

It’s okay to store string literals in character arrays as just described. The new strings that you assign with = can be shorter or longer than the previous strings. That’s nice, because you might recall that you can’t store a string into a character array that is longer than the array you reserved initially.

You must be extremely careful, however, not to let the program store strings longer than the first string you point to with the character pointer. This is a little complex, but keep following along because this chapter stays as simple and short as possible. Never set up a character pointer variable like this:

image

and then later let the user enter a new string with gets() like this:

gets(name); /* Not very safe */

The problem with this statement is that the user might enter a string longer than Tom Roberts, the first string assigned to the character pointer. Although a character pointer can point to strings of any length, the gets() function, along with scanf(), strcpy(), and strcat(), doesn’t know that it’s being sent a character pointer. Because they might be sent a character array that can’t change location, these functions map the newly created string directly over the location of the string in name. If a string longer than name is entered, other data areas could be overwritten.

Warning

image

Yes, this is a little tedious. You might have to read this section again later after you get more comfortable with pointers and arrays.

If you want to have the advantage of a character pointer—that is, if you want to be able to assign string literals to the pointer and still have the safety of arrays so you can use the character pointer to get user input—you can do so with a little trick.

If you want to store user input in a string pointed to by a pointer, first reserve enough storage for that input string. The easiest way to do this is to reserve a character array and then assign a character pointer to the beginning element of that array:

image

Now you can input a string by using the pointer:

gets(iptr);  /* Makes sure that iptr points to
                the string typed by the user */

as long as the string entered by the user is not longer than 81 bytes long. There is a nice string-input function you can use to ensure that entered strings don’t get longer than 81 characters, including the null zero. Use fgets() if you want to limit the number of characters accepted from the user. fgets() works like gets(), except that you specify a length argument. The following statement shows fgets() in action:

fgets(iptr, 81, stdin);  /*Gets up to 80 chars and adds null
                           zero */

The second value is the maximum number of characters you want to save from the user’s input. Always leave one for the string’s null zero. The pointer iptr can point to a string as long as 81 characters. If the user enters a string less than 81 characters, iptr points to that string with no problem. If, however, the user goes wild and enters a string 200 characters long, iptr points only to the first 80, followed by a null zero at the 81st position that fgets() added, and the rest of the user’s input is ignored.

Clue

image

You can use fgets() to read strings from data files. The third value of fgets() can be a disk file pointer, but you’ll learn about disk pointers later in the book. For now, use stdin as the third value you send to fgets() so that fgets() goes to the keyboard for input and not somewhere else.

You also can assign the pointer string literals using the assignment like this:

iptr = "William Harper Littlejohn";

Arrays of Pointers

If you want to use a bunch of pointers, create an array of them. An array of pointers is just as easy to define as an array of any other kind of data, except that you must include the * operator after the data type name. The following statements reserve an array of 25 integer pointers and an array of 25 character pointers:

int * ipara[25];   /* 25 pointers to integers */
char * cpara[25];  /* 25 pointers to characters */

The array of characters is most interesting because you can store a list of strings in the array. More accurately, you can point to various strings. The following program illustrates two things: how to initialize an array of strings at definition time and how to print them using a for loop:

image

Here is the output from this program:

image

Figure 25.2 shows how the program sets up the names array in memory. Each element is nothing more than a character pointer that contains the address of a different person’s name. It’s important that you understand names does not hold strings, just pointers to strings.

Figure 25.2. The names array contains pointers to strings.

image

See, even though there is no such thing as a string array in C (because there are no string variables), storing character pointers in names makes the program act as though names is a string array.

Rewards

image

• Use character pointers if you want to assign string literals directly.

• Use either array subscript notation or pointer dereferencing to access array and pointer values.

• Take a break. This was a lot of material!

Pitfalls

image

• Don’t use a built-in function to fill a character pointer’s location unless that character pointer was originally set up to point to a long string.

In Review

The goal of this chapter was to get you thinking about the similarities between arrays and pointers. An array name is really just a pointer that points to the first element in the array. Unlike pointer variables, an array name can’t change. This is the primary reason an array name can’t appear on the left side of an equals sign.

Using pointers allows more flexibility than arrays. You can directly assign a string literal to a character pointer variable, whereas you must use the strcpy() function to assign strings to arrays. You’ll see many uses for pointer variables throughout your C programming career.

Code Example

image

Code Analysis

The array of seven pointer variables is created and then assigned to the seven days of the week string literals. The strings could have been assigned when days was defined, but this code assigns each string one at a time, just to show you how it can be done.

The program then asks for a number. If the user enters a number from 1 to 7, the matching day element is printed. Because array elements begin at 0, 1 has to be subtracted from the user’s number to match a day of the week name.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.234.83