Read Sams Teach Yourself C in 24 Hours Online
Authors: Tony. Zhang
17: main(void)
18: {
19: char *str[MAX_NUM] = {“The choice of a point of view”,
20: “is the initial act of culture.”,
21: “--- by O. Gasset”};
22:
23: #if TEST_1 == 1
24: #if TEST_2 == 2
25: #if TEST_3 == 3
26: StrPrint(str, MAX_NUM);
27: #else
28: StrPrint(str, MAX_NUM - ONE);
29: #endif
30: #else
31: StrPrint(str, MAX_NUM - TWO);
32: #endif
33: #else
34: printf(“No TEST macro has been set.\n”);
35: #endif
continues
29 067231861x CH23 1/25/00 11:03 AM Page 404
404
Hour 23
LISTING 23.4
continued
36:
37: return NO_ERROR;
38: }
39: /* function definition */
40: void StrPrint(char **ptr_s, int max)
41: {
42: int i;
43:
44: for (i=0; i
45: printf(“Content: %s\n”,
46: ptr_s[i]);
47: }
The following output is shown on the screen after the executable 23L04.exe is created and run on my machine:
Content: The choice of a point of view
OUTPUT
Content: is the initial act of culture.
Content: --- by O. Gasset
The purpose of the program in Listing 23.4 is to print the content of character
ANALYSIS
strings controlled by the nested #if directives.
At the beginning of the program, nine macro names are defined in lines 5–13. The prototype of a function, StrPrint(), is given in line 15. Lines 19–21 define and initialize an array of char pointers called str.
The #if directives in lines 23–25 evaluate macro names, TEST_1, TEST_2, and TEST_3, respectively. If the three macro names all evaluate to nonzero values, thenStrPrint() is called in line 26 to print the content of all character strings pointed to by the pointers in the str array.
If, however, only TEST_1 and TEST_2 are nonzero, the statement in line 28 prints out the content of the MAX_NUM-ONE strings. Likewise, if only TEST_1 evaluates to a nonzero value, the StrPrint() function is called in line 31 to print out the content of the MAX_NUM-TWO strings.
The last case is that TEST_1, TEST_2, and TEST_3 all return zero. Then the printf() call in line 34 is executed to display onscreen the message No TEST macro has been set.
As you can tell from the program in Listing 23.4, TEST_1, TEST_2, and TEST_3 are all defined with nonzero constants; the content of all character strings referenced by the pointers of the str array are printed out as the output from the program.
You can experiment with the effects of these nested directives by changing the values of the macros TEST_1, TEST_2, and TEST_3.
29 067231861x CH23 1/25/00 11:03 AM Page 405
Compiling Programs: The C Preprocessor
405
Summary
In this lesson you learned the following important concepts and directives regarding the preprocessor in C:
• The C preprocessor runs before the compiler. During the preprocessing stage, all occurrences of a macro name are replaced by the macro body that is associated with the macro name.
23
• The C preprocessor also enables you to include additional source files in the program or compile sections of C code conditionally.
• The C preprocessor is not part of the C compiler.
• A macro statement ends with a newline character, not a semicolon.
• The #define directive tells the preprocessor to replace every occurrence of a macro name defined by the directive with a macro body that is associated with the macro name.
• The #undef directive is used to remove the definition of a macro name that has been previously defined.
• You can specify one or more arguments to a macro name defined by the #define directive.
• The #ifdef directive enables you to specify code that is to be included only when a particular macro name is defined.
• The #ifndef directive is a mirror directive to the #ifdef directive. With #ifndef, you specify code that is to be included when a particular macro name is not defined.
• The #endif directive is used to mark the end of an #ifdef, an #ifndef, or an #if block.
• The #if, #elif, and #else directives enable you to select alternate portions of code to compile.
In the next lesson you’ll see a summary of what you’ve learned and what you can do after studying this book.
Q&A
Q Is the C preprocessor part of the C compiler?
A
No. The C preprocessor is not part of the C compiler. With its own line-oriented grammar and syntax, the C preprocessor runs before the compiler in order to han-dle named constants, macros, and inclusion of files.
29 067231861x CH23 1/25/00 11:03 AM Page 406
406
Hour 23
Q How do you remove a macro name?
A
By using the #undef directive with a macro name, that macro name can be removed, or “undefined.” According to the ANSI C standard, a macro name has to be removed before it can be redefined.
Q Why do you need the
#endif
directive?
A
The #endif directive is used with an #if, #ifdef, or #ifndef directives because statements under the control of a conditional preprocessor directive are not enclosed in braces ({ and }). Therefore, #endif must be used to mark the end of the block of statements.
Q Can the conditional expression following the
#if
directive be an arithmetic
expression?
A
Yes. The conditional expression evaluated by the #if directive can be an arithmetic expression. If the expression evaluates to a nonzero value, the code between the
#if directive and the next nearest conditional directive are included for compilation. Otherwise, the code is skipped entirely and will not be part of the compiled program.
Workshop
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. What’s wrong with the following macro definition?
#define ONE 1;
2. What is the final value assigned to result after the assignment statement is executed?
#define ONE 1
#define NINE 9
#define EXPRESS ONE + NINE
result = EXPRESS * NINE;
3. What message will be displayed by the following code segment?
#define MACRO_NAME 0
#if MACRO_NAME
printf(“Under #if.\n”);
#else
printf(“Under #else.\n”);
#endif
29 067231861x CH23 1/25/00 11:03 AM Page 407
Compiling Programs: The C Preprocessor
407
4. What message will be displayed by the following code segment?
#define MACRO_NAME 0
#ifdef MACRO_NAME
printf(“Under #ifdef.\n”);
#endif
#ifndef MACRO_NAME
printf(“Under #ifndef.\n”);
#endif
23
Exercises
1. In Hour 18, “Using Special Data Types and Functions,” you learned how to define enum data. Rewrite the program in Listing 18.1 with the #define directive.
2. Define a macro name that can multiply two arguments. Write a program to calculate the multiplication of 2 and 3 with the help of the macro. Print out the result of the multiplication.
3. Rewrite the program in Listing 23.2 with the #if, #elif, and #else directives.
4. Rewrite the program in Listing 23.3 with nested #if directives.
29 067231861x CH23 1/25/00 11:03 AM Page 408
30 067231861x CH24 1/25/00 10:48 AM Page 409
HOUR 24
Where Do You Go from
Here?
It’s not what you know, but what you can.
—A. Alekhine
Congratulations! You’re now in the last chapter of this book. You just need to spend one more hour to complete your 24-hour journey. In this lesson you’ll learn more about the C language from the following topics:
• Programming style
• Modular programming
• Debugging
Also, a brief review on what you’ve learned from this book is included in this lesson. Before you start to cover these topics, let’s have a look at the last example in this book.
30 067231861x CH24 1/25/00 10:48 AM Page 410
410
Hour 24
Creating a Linked List
In this section, I’m going to build functions that can create a linked list, and add items to or delete items from the created linked list. I save those functions into a source file (that is, a
module
; refer to the section “Modular Programming” in this lesson). In addition, I will set up an interface between the module file and the user. In other words, the user can call one of the functions saved in the module via the interface. The interface is invoked in the main() function that is saved in another source file. I will put data declarations and function prototypes in a separate header file.
A
linked list
is a chain of nodes (or elements). Each node consists of data items and a pointer that points to the next node in the list. The last item has a null pointer to signify the end of the list.
A linked list is a very powerful, and very versatile, data structure. No matter what programming project you eventually undertake, it’s likely that you’ll want to use a linked list at some point. Why are linked lists so popular? For starters, they are relatively easy to implement, unlike some other data structures that may be more powerful but get complicated quickly. Secondly, it is easy to “walk” a linked list by simply following the pointers along. It’s almost as easy as using an array, but with a linked list you have the flexibility of dynamic memory allocation.
A linked list with N nodes is shown in Figure 24.1.
FIGURE 24.1
Head
node 1
node 2
• • •
A linked list with N
nodes.
Null
As you can see from Figure 24.1, a start pointer points to the first node in the list. The pointer in the last (
N
th) node is a null pointer.
The linked list I’m going to build is a very simple one, in which each element only contains two items: a student name and an ID number. Listing 24.1 contains the module program, which is saved in the source file named 24L01.c.
TYPE
LISTING 24.1
Putting Cohesive Functions in the Module Program
1: /* 24L01.c: A module file */
2: #include “24L02.h”
3:
4: static NODE *head_ptr = NULL;
5:
30 067231861x CH24 1/25/00 10:48 AM Page 411
Where Do You Go From Here?
411
6: /**
7: ** main_interface()
8: **/
9: void main_interface(int ch)
10: {
11: switch (ch){
12: case ‘a’:
13: list_node_add();
14: break;
15: case ‘d’:
16: if (!list_node_delete())
17: list_node_print();
18: break;
19: case ‘p’:
20: list_node_print();
21: break;
22: default:
24
23: break;
24: }
25: }
26: /**
27: ** list_node_create()
28: **/
29: NODE *list_node_create(void)
30: {
31: NODE *ptr;
32:
33: if ((ptr=(NODE *)malloc(sizeof(NODE))) == NULL)
34: ErrorExit(“malloc() failed.\n”);
35:
36: ptr->next_ptr = NULL; /* set the next pointer to NULL */
37: ptr->id = 0; /* initialization */
38: return ptr;
39: }
40:
41: /**
42: ** list_node_add()
43: **/
44: void list_node_add(void)
45: {
46: NODE *new_ptr, *ptr;
47:
48: new_ptr = list_node_create();
49: printf(“Enter the student name and ID: “);
50: scanf(“%s%ld”, new_ptr->name, &new_ptr->id);
51:
52: if (head_ptr == NULL){
53: head_ptr = new_ptr;
54: } else {
continues
30 067231861x CH24 1/25/00 10:48 AM Page 412
412
Hour 24
LISTING 24.1
continued
55: /* find the last node in the list */
56: for (ptr=head_ptr;
57: ptr->next_ptr != NULL;
58: ptr=ptr->next_ptr)
59: ; /* doing nothing here */
60: /* link to the last node */