Sams Teach Yourself C in 24 Hours (44 page)

BOOK: Sams Teach Yourself C in 24 Hours
13.46Mb size Format: txt, pdf, ePub

Pointers are very useful when used properly. However, a pointer can get you into trouble quickly if it contains the wrong value. A common error, for instance, is to assign a right value to a pointer that actually expects a left one. Fortunately, many C compilers will find such errors and issue a warning message.

There is another common error that the compiler does not always pick up for you: using uninitialized pointers. For example, the following code has a potential problem:

int x, *ptr_int;

x = 8;

*ptr_int = x;

The problem is that the ptr_int pointer is not initialized; it points to some unknown memory location. Therefore, assigning a value, like 8 in this case, to an unknown memory location is dangerous. It may overwrite some

important data that are already saved at the memory location, thus causing a serious problem. The solution is to make sure that a pointer is pointing at a legal and valid memory location before it is used.

You can rewrite the above code to avoid the potential problem like this: int x, *ptr_int;

x = 8;

ptr_int = &x; /* initialize the pointer */

21 067231861x CH16 1/25/00 10:35 AM Page 263

Applying Pointers

263

Pointer Subtraction

You can subtract one pointer value from the other to obtain the distance between the two memory locations. For instance, given two char pointer variables, ptr_str1 and ptr_str2, you can calculate the offset between the two memory locations pointed to by the two pointers like this:

ptr_str2 - ptr_str1

16

To get meaningful results, it is best to only subtract pointers of the same data type.

Listing 16.2 shows an example of performing subtraction on an int pointer variable.

TYPE

LISTING 16.2

Performing Subtraction on Pointers

1: /* 16L02.c: Pointer subtraction */

2: #include

3:

4: main()

5: {

6: int *ptr_int1, *ptr_int2;

7:

8: printf(“The position of ptr_int1: %p\n”, ptr_int1);

9: ptr_int2 = ptr_int1 + 5;

10: printf(“The position of ptr_int2 = ptr_int1 + 5: %p\n”, ptr_int2); 11: printf(“The subtraction of ptr_int2 - ptr_int1: %d\n”, ptr_int2 -

ptr_int1);

12: ptr_int2 = ptr_int1 - 5;

13: printf(“The position of ptr_int2 = ptr_int1 - 5: %p\n”, ptr_int2); 14: printf(“The subtraction of ptr_int2 - ptr_int1: %d\n”, ptr_int2 -

ptr_int1);

15:

16: return 0;

17: }

After running the executable (16L02.exe) of the program in Listing 16.2 on my machine, I have the following output shown on the screen:

The position of ptr_int1: 0x0128

OUTPUT
The position of ptr_int2 = ptr_int1 + 5: 0x0132

The subtraction of ptr_int2 - ptr_int1: 5

The position of ptr_int2 = ptr_int1 - 5: 0x011E

The subtraction of ptr_int2 - ptr_int1: -5

The program in Listing 16.2 declares two int pointer variables, ptr_int1 and
ANALYSIS
ptr_int2, in line 6. The statement in line 8 prints out the memory position held by ptr_int1. Line 9 assigns the memory address referenced by ptr_int1+5 to ptr_int2.

Then, the content of ptr_int2 is printed out in line 10.

21 067231861x CH16 1/25/00 10:35 AM Page 264

264

Hour 16

The statement in line 11 shows the difference between the two int pointers—that is, the subtraction of ptr_int2 and ptr_int1. The result is 5.

Line 12 then assigns another memory address, referenced by the expression ptr_int1-5, to the ptr_int2 pointer. Now, ptr_int2 points to a memory location that is 10 bytes lower than the memory location pointed by ptr_int1 (see the output made by line 13.) The difference between ptr_int2 and ptr_int1 is obtained by the subtraction of the two pointers, which is -5 (since an int on my machine is two bytes) as printed out by the statement in line 14.

Pointers and Arrays

As indicated in previous lessons, pointers and arrays have a close relationship. You can access an array through a pointer that contains the start address of the array. The following subsection introduces how to access array elements through pointers.

Accessing Arrays via Pointers

Because an array name that is not followed by a subscript is interpreted as a pointer to the first element of the array, you can assign the start address of the array to a pointer of the same data type; then you can access any element in the array by adding a proper integer to the pointer. The value of the integer you use is the same as the subscript value of the element that you want to access.

In other words, given an array, array, and a pointer, ptr_array, if array and ptr_array are of the same data type, and ptr_array contains the start address of the array, that is ptr_array = array;

then the expression array[n] is equivalent to the expression

*(ptr_array + n)

Here n is a subscript number in the array.

Listing 16.3 demonstrates how to access arrays and change values of array elements by using pointers.

TYPE

LISTING 16.3

Accessing Arrays by Using Pointers

1: /* 16L03.c: Accessing arrays via pointers */

2: #include

3:

4: main()

5: {

21 067231861x CH16 1/25/00 10:35 AM Page 265

Applying Pointers

265

6: char str[] = “It’s a string!”;

7: char *ptr_str;

8: int list[] = {1, 2, 3, 4, 5};

9: int *ptr_int;

10:

11: /* access char array */

12: ptr_str = str;

13: printf(“Before the change, str contains: %s\n”, str);

14: printf(“Before the change, str[5] contains: %c\n”, str[5]);

15: *(ptr_str + 5) = ‘A’;

16

16: printf(“After the change, str[5] contains: %c\n”, str[5]);

17: printf(“After the change, str contains: %s\n”, str);

18: /* access int array */

19: ptr_int = list;

20: printf(“Before the change, list[2] contains: %d\n”, list[2]);

21: *(ptr_int + 2) = -3;

22: printf(“After the change, list[2] contains: %d\n”, list[2]);

23:

24: return 0;

25: }

The following output is displayed after the executable file 16L03.exe is created and run on my computer:

Before the change, str contains: It’s a string!

OUTPUT
Before the change, str[5] contains: a

After the change, str[5] contains: A

After the change, str contains: It’s A string!

Before the change, list[2] contains: 3

After the change, list[2] contains: -3

The purpose of the program in Listing 16.3 is to show you how to access a char
ANALYSIS
array, str, and an int array, list. In lines 6 and 8, str and list are declared and initialized with a string and a set of integers, respectively. A char pointer, ptr_str, and an int pointer, ptr_int, are declared in lines 7 and 9.

Line 12 assigns the start address of the str array to the ptr_str pointer. The statements in lines 13 and 14 demonstrate the content of the string saved in the str array, as well as the character contained by the str[5] element in the array before any changes are made to str.

The statement in line 15 shows that the character constant, ‘A’, is assigned to the element of the str array pointed by the expression

*(ptr_str + 5)

To verify that the content of the element in str has been updated, lines 16 and 17 print out the element and the whole string, respectively. The output indicates that ‘A’ has replaced the original character constant, ‘a’.

21 067231861x CH16 1/25/00 10:35 AM Page 266

266

Hour 16

The start address of the int array list is assigned to the ptr_int pointer in line 19.

Before I do anything with the list[2] element of the list array, I print out its value, which is 3 at this moment (see the output made by line 20). In line 21, the list[2] element is given another value, -3, through the dereferenced pointer *(ptr_int + 2). The printf() call in line 22 prints the updated value of list[2] .

Pointers and Functions

Before I start to talk about passing pointers to functions, let’s first have a look how to pass arrays to functions.

Passing Arrays to Functions

In practice, it’s usually awkward if you pass more than five or six arguments to a function. One way to save the number of arguments passed to a function is to use arrays. You can put all variables of the same type into an array, and then pass the array as a single argument.

The program in Listing 16.4 shows how to pass an array of integers to a function.

TYPE

LISTING 16.4

Passing Arrays to Functions

1: /* 16L04.c: Passing arrays to functions */

2: #include

3:

4: int AddThree(int list[]);

5:

6: main()

7: {

8: int sum, list[3];

9:

10: printf(“Enter three integers separated by spaces:\n”);

11: scanf(“%d%d%d”, &list[0], &list[1], &list[2]);

12: sum = AddThree(list);

13: printf(“The sum of the three integers is: %d\n”, sum);

14:

15: return 0;

16: }

17:

18: int AddThree(int list[])

19: {

20: int i;

21: int result = 0;

22:

23: for (i=0; i<3; i++)

24: result += list[i];

25: return result;

26: }

21 067231861x CH16 1/25/00 10:36 AM Page 267

Applying Pointers

267

The following output is obtained after I run the executable, 16L04.exe, and enter three integers, 10, 20, and 30, on my machine:

Enter three integers separated by spaces:

OUTPUT
10 20 30

The sum of the three integers is: 60

The purpose of the program in Listing 16.4 is to obtain three integers entered by
ANALYSIS
the user, and then pass the three integers as an array to a function called
16

AddThree() to perform the operation of addition.

Line 4 gives the declaration of the AddThree() function. Note that the unsized array, list[], is used in the argument expression, which indicates that the argument contains the start address of the list array.

The list array and an integer variable, sum, are declared in line 8. The printf() call in line 10 displays a message asking the user to enter three integers. Then, line 11 uses scanf() to retrieve the integers entered by the user and stores them into the three memory locations of the elements in the integer array referenced by &list[0], &list[1], and

&list[2], respectively.

The statement in line 12 calls the AddThree() function with the name of the array as the argument. The AddThree(list) expression is actually passing the start address of the list array (&list[0]) to the AddThree() function.

The definition of the AddThree() function is in lines 18–26; it adds the values of all three elements in the list array and returns the result of the addition. The result returned from the AddThree() function is assigned to the integer variable sum in line 12 and is printed out in line 13.

You can also specify the size of an array that is passed to a function. For instance, the following:

function(char str[16]);

is equivalent to the following statement:

function(char str[]);

Remember that the compiler can figure out the size for the unsized

array str[].

For multidimensional arrays, the format of an unsized array should be

always used in the declaration. (See the section titled “Passing

Multidimensional Arrays as Arguments,” later in this hour.)

21 067231861x CH16 1/25/00 10:36 AM Page 268

268

Hour 16

Passing Pointers to Functions

As you know, an array name that is not followed by a subscript is interpreted as a pointer to the first element of the array. In fact, the address of the first element in an array is the start address of the array. Therefore, you can assign the start address of an array to a pointer, and then pass the pointer name, instead of the unsized array, to a function.

Listing 16.5 shows an example of passing pointers to functions, which is similar to passing arrays that are passed to functions.

TYPE

LISTING 16.5

Passing Pointers to Functions

1: /* 16L05.c: Passing pointers to functions */

2: #include

3:

4: void ChPrint(char *ch);

5: int DataAdd(int *list, int max);

6: main()

7: {

8: char str[] = “It’s a string!”;

9: char *ptr_str;

10: int list[5] = {1, 2, 3, 4, 5};

11: int *ptr_int;

12:

13: /* assign address to pointer */

14: ptr_str = str;

15: ChPrint(ptr_str);

16: ChPrint(str);

17:

18: /* assign address to pointer */

19: ptr_int = list;

20: printf(“The sum returned by DataAdd(): %d\n”,

21: DataAdd(ptr_int, 5));

22: printf(“The sum returned by DataAdd(): %d\n”,

23: DataAdd(list, 5));

24: return 0;

25: }

26: /* function definition */

27: void ChPrint(char *ch)

28: {

29: printf(“%s\n”, ch);

30: }

31: /* function definition */

32: int DataAdd(int *list, int max)

33: {

34: int i;

35: int sum = 0;

36:

21 067231861x CH16 1/25/00 10:36 AM Page 269

Applying Pointers

269

37: for (i=0; i

38: sum += list[i];

39: return sum;

40: }

After executing the 16L05.exe program, I obtain the following output displayed on the screen of my computer:

Other books

Cry For the Baron by John Creasey
Gun for Revenge by Steve Hayes
Mira in the Present Tense by Sita Brahmachari
First Gravedigger by Barbara Paul
The Bone Artists by Madeleine Roux
Words by Ginny L Yttrup
Dying To Marry by Janelle Taylor
Hot Blue Velvet by Elliott, Leanore
Sweet by Alysia Constantine