Sams Teach Yourself C in 24 Hours (43 page)

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

On the other hand, to solve a problem, you can first work out an outline and start your programming at a higher level. For instance, you can work on the main() function at the beginning, and then move to the next lower level until the lowest-level functions are written. This type of approach is called
top-down programming
.

You’ll find that it’s useful to combine these two types of structured programming and use them alternately in order to solve real problems.

Summary

In this lesson you learned the following important concepts about functions in C:

• A function declaration alludes to a function that is defined elsewhere, and specifies what type of arguments and values are passed to and returned from the function as well.

• A function definition reserves the memory space and defines what the function does, as well as the number and type of arguments passed to the function.

• A function can be declared to return any data type, except an array or a function.

• The return statement used in a function definition returns a single value whose type must be matched with the one declared in the function declaration.

• A function call is an expression that can be used as a single statement or within other expressions or statements.

• The void data type is needed in the declaration of a function that takes no argument.

• To declare a function that takes a variable number of arguments, you have to specify at least the first argument, and use the ellipsis (...) to represent the rest of the arguments passed to the function.

20 067231861x CH15 4.10.2000 11:03 AM Page 256

256

Hour 15

• va_start(), va_arg(), and va_end(), all included in stdarg.h, are needed in processing a variable number of arguments passed to a function.

• time(), localtime(), and asctime() are three time functions provided by C. They can be used together to obtain a character string that contains information about the local date and time based on the calendar time.

In the next lesson you’ll learn more about pointers and their applications in C.

Q&A

Q What is the main difference between a function declaration and a function
definition?

A
The main difference between a function declaration and a function definition is that the former does not reserve any memory space, nor does it specify what a function does. A function declaration only alludes to a function definition that is placed elsewhere. It also specifies what type of arguments and values are passed to and returned from the function. A function definition, on the other hand, reserves the memory space and specifies tasks the function can complete.

Q Why do we need function prototypes?

A
By declaring a function with prototypes, you specify not only the data type returned by the function, but also the types and names of arguments passed to the function. With the help of a function prototype, the compiler can automatically perform type checking on the definition of the function, which saves you time in debugging the program.

Q Can a function return a pointer?

A
Yes. In fact, a function can return a single value that can be any data type except an array or a function. A pointer value—that is, the address—returned by a function can refer to a character array, or a memory location that stores other types of data.

For instance, the C library function asctime() returns a character pointer that points to a character string converted from a date-time structure.

Q Can you use top-down programming and bottom-up programming together to
solve a problem?

A
Yes. In practice, you can find that it’s actually a good idea to combine the top-down and bottom-up programming approaches together to solve problems. Using the two types of structured programming can make your program easy to write and understand.

20 067231861x CH15 4.10.2000 11:03 AM Page 257

Working with Functions

257

Workshop

15

To help solidify your understanding of this hour’s lesson, you are encouraged to answer the quiz questions and finish the exercises provided in the workshop before you move to the next lesson. The answers and hints to the questions and exercises are given in Appendix B, “Answers to Quiz Questions and Exercises.”

Quiz

1. Given the following function declarations, which ones are functions with fixed number of arguments, which ones are functions with no arguments, and which ones are functions with a variable number of arguments?

• int function_1(int x, float y);

• void function_2(char *str);

• char *asctime(const struct tm *timeptr);

• int function_3(void);

• char function_4(char c, ...);

• void function_5(void);

2. Which one in the following two expressions is a function definition?

int function_1(int x, int y);

int function_2(int x, int y){return x+y;}

3. What is the data type returned by a function when a type specifier is omitted?

4. In the following function declarations, which ones are illegal?

• double function_1(int x, ...);

• void function_2(int x, int y, ...);

• char function_3(...);

• int function_4(int, int, int, int);

Exercises

1. Rewrite the program in Listing 15.2. This time use the format specifier %c, instead of %s, to print out the character string of the local time on your computer.

2. Declare and define a function, called MultiTwo(), that can perform multiplication on two integer variables. Call the MultiTwo() function from the main() function and pass two integers to MultiTwo(). Then print out the result returned by the MultiTwo() function on the screen.

20 067231861x CH15 4.10.2000 11:03 AM Page 258

258

Hour 15

3. Rewrite the program in Listing 15.3. This time, make a function that takes a variable number of int arguments and performs the operation of multiplication on these arguments.

4. Rewrite the program in Listing 15.3 again. This time, print out all arguments passed to the AddDouble() function. Does va_arg() fetch each argument in the same order (that is, from left to right) of the argument list passed to AddDouble()?

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

HOUR 16

Applying Pointers

Think twice and do once.

—Chinese proverb

In Hour 11, “Understanding Pointers,” you learned the basics of using pointers in C. Because pointers are very useful in programming, it’s worth spend-ing another hour to learn more about them. In this lesson, the following topics are discussed:

• Pointer arithmetic

• Passing arrays to functions

• Passing pointers to functions

• Pointing to functions

Pointer Arithmetic

In C, you can move the position of a pointer by adding or subtracting integers to or from the pointer. For example, given a character pointer variable ptr_str, the following expression:

ptr_str + 1

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

260

Hour 16

moves the pointer to the memory location that is one byte away from the current position of ptr_str.

Note that for pointers of different data types, the integers added to or subtracted from the pointers have different sizes. In other words, adding (or, subtracting) 1 to a pointer is not necessarily instructing the compiler to add (or subtract) one byte to the address, but rather to adjust the address so that it skips over one element of the type of the pointer.

You’ll see more details in the following sections.

The Scalar Size of Pointers

The general format to change the position of a pointer is

pointer_name + n

Here n is an integer whose value can be either positive or negative. pointer_name is the name of a pointer variable that has the following declaration:

data_type_specifier *pointer_name;

When the C compiler reads the expression pointer_name + n, it interprets it as pointer_name + n * sizeof(data_type_specifier)

Note that the sizeof operator is used to obtain the number of bytes of the specified data type. Therefore, for the char pointer variable ptr_str, the expression ptr_str + 1 actually means

ptr_str + 1 * sizeof(char).

Because the size of a character is one byte long, ptr_str + 1 tells the compiler to move to the memory location that is 1 byte after the current location referenced by the pointer.

The program in Listing 16.1 shows how the scalar sizes of different data types affect the offsets added to or subtracted from pointers.

TYPE

LISTING 16.1

Moving Pointers of Different Data Types

1: /* 16L01.c: Pointer arithmetic */

2: #include

3:

4: main()

5: {

6: char *ptr_ch;

7: int *ptr_int;

8: double *ptr_db;

9: /* char pointer ptr_ch */

10: printf(“Current position of ptr_ch: %p\n”, ptr_ch);

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

Applying Pointers

261

11: printf(“The position after ptr_ch + 1: %p\n”, ptr_ch + 1);

12: printf(“The position after ptr_ch + 2: %p\n”, ptr_ch + 2);

13: printf(“The position after ptr_ch - 1: %p\n”, ptr_ch - 1);

14: printf(“The position after ptr_ch - 2: %p\n”, ptr_ch - 2);

15: /* int pointer ptr_int */

16: printf(“Current position of ptr_int: %p\n”, ptr_int);

17: printf(“The position after ptr_int + 1: %p\n”, ptr_int + 1);

18: printf(“The position after ptr_int + 2: %p\n”, ptr_int + 2);

19: printf(“The position after ptr_int - 1: %p\n”, ptr_int - 1);

20: printf(“The position after ptr_int - 2: %p\n”, ptr_int - 2);

16

21: /* double pointer ptr_ch */

22: printf(“Current position of ptr_db: %p\n”, ptr_db);

23: printf(“The position after ptr_db + 1: %p\n”, ptr_db + 1);

24: printf(“The position after ptr_db + 2: %p\n”, ptr_db + 2);

25: printf(“The position after ptr_db - 1: %p\n”, ptr_db - 1);

26: printf(“The position after ptr_db - 2: %p\n”, ptr_db - 2);

27:

28: return 0;

29: }

The following output is obtained by running the executable file 16L01.exe of the program in Listing 16.1 on my machine. You might get different addresses on your computer, as well as different offsets depending on the sizes of the data types on your system:

Current position of ptr_ch: 0x000B

OUTPUT
The position after ptr_ch + 1: 0x000C

The position after ptr_ch + 2: 0x000D

The position after ptr_ch - 1: 0x000A

The position after ptr_ch - 2: 0x0009

Current position of ptr_int: 0x028B

The position after ptr_int + 1: 0x028D

The position after ptr_int + 2: 0x028F

The position after ptr_int - 1: 0x0289

The position after ptr_int - 2: 0x0287

Current position of ptr_db: 0x0128

The position after ptr_db + 1: 0x0130

The position after ptr_db + 2: 0x0138

The position after ptr_db - 1: 0x0120

The position after ptr_db - 2: 0x0118

As you can see in Listing 16.1, there are three pointers of different types—

ANALYSIS
ptr_ch, ptr_int, and ptr_db—declared in lines 6–8. Among them, ptr_ch is a pointer to a character, ptr_int is a pointer to an integer, and ptr_db is a pointer to a double.

Then the statement in line 10 shows the memory address, 0x000B, contained by the char pointer variable ptr_ch. Lines 11 and 12 display the two addresses, 0x000C and 0x000D, when ptr_ch is added with 1 and 2, respectively. Similarly, lines 13 and 14 give 0x000A 21 067231861x CH16 1/25/00 10:35 AM Page 262

262

Hour 16

and 0x0009 when ptr_ch is moved down to lower memory addresses. Because the size of char is 1 byte, ptr_ch+1 means to move to the memory location that is 1 byte higher than the current memory location, 0x000B, referenced by the pointer ptr_ch.

Line 16 shows the memory location referenced by the int pointer variable ptr_int at 0x028B. Because the size of int is 2 bytes long on my system, the expression ptr_int+1

moves ptr_int to the memory location that is 2 bytes higher than the current one pointed to by ptr_int. That’s exactly the result you see in line 17. Likewise, line 18

shows that ptr_int+2 moves the reference to 0x028F, which is 4 bytes higher (2*sizeof(int)) than 0x028B. The memory location 0x0289 is referenced by the expression ptr_int-1 in line 19; 0x0287 is referenced by ptr_int-2 in line 20.

The size of the double data type is 8 bytes long on my system. Therefore, the expression ptr_db+1 is interpreted as the memory address referenced by ptr_db plus 8 bytes—that is, 0x0128+8, which gives 0x0130 in hex format ,as you can see in line 23.

Lines 24–26 print out the memory addresses referenced by ptr_db+2, ptr_db-1, and ptr_db-2, respectively, which prove that the compiler has used the same scalar size of double in the pointer arithmetic.

Other books

Taken for English by Olivia Newport
Lady Jane's Ribbons by Sandra Wilson
Endangered by Lamar Giles
Stage Fright by Peter Bently
The New Year Resolution by Rose-Innes, Louise
Children Of Fiends by C. Chase Harwood
Sand Sharks by Margaret Maron