Chapter 6 DEFINES AND MACROS AIDS TO CLEAR PROGRAMMING ____________________________________________________________ Load and display the file named DEFINE.C for ============== your first look at some defines and macros. DEFINE.C Notice lines 4 through 7 of the program, each ============== starting with #define. This is the way all defines and macros are defined. Before the actual compilation starts, the compiler goes through a preprocessor pass to resolve all of the defines. In the present case, it will find every place in the program where the combination START is found and it will replace it with the 0 since that is the definition. The compiler itself will never see the word START, so as far as the compiler is concerned, the zeros were always there. Note that if the string is found in a string constant or in a comment, it will not be changed. It should be clear to you that putting the word START in your program instead of the numeral 0 is only a convenience to you and actually acts like a comment since the word START helps you to understand what the zero is used for. In the case of a very small program, such as that before you, it doesn't really matter what you use. If, however, you had a 2000 line program before you with 27 references to START, it would be a completely different matter. If you wanted to change all of the STARTs in the program to a new number, it would be simple to change the one #define. If this technique were not used, it would be difficult to find and change all of the references to it manually, and possibly disastrous if you missed one or two of the references. In the same manner, the preprocessor will find all occurrences of the word ENDING and change them to 9, then the compiler will operate on the changed file with no knowledge that ENDING ever existed. It is a fairly common practice in C programming to use all capital letters for a symbolic constant such as START and ENDING and use all lower case letters for variable names. You can use any method you choose since it is mostly a matter of personal taste. Page 6-1 Chapter 6 - Defines and Macros IS THIS REALLY USEFUL? ____________________________________________________________ When we get to the chapters discussing input and output, we will need an indicator to tell us when we reach the end-of-file of an input file. Since different compilers use different numerical values for this, although most use either a zero or a minus 1, we will write the program with a #define to define the EOF used by our particular compiler. If at some later date, we change to a new compiler, it is a simple matter to change this one #define to fix the entire program. In most C compilers, the EOF is defined in the STDIO.H file. You can observe this for yourself by listing the STDIO.H file that was supplied with your compiler. WHAT IS A MACRO? ____________________________________________________________ A macro is nothing more than another define, but since it is capable of at least appearing to perform some logical decisions or some math functions, it has a unique name. Consider line 6 of the program on your screen for an example of a macro. In this case, anytime the preprocessor finds the word MAX followed by a group in parentheses, it expects to find two terms in the parentheses and will do a replacement of the terms into the second part of the definition. Thus the first term will replace every A in the second part of the definition and the second term will replace every B in the second part of the definition. When line 15 of the program is reached, index will be substituted for every A, and count will be substituted for every B. Once again, it must be stated that string constants and comments will not be affected. Remembering the cryptic construct we studied a couple of chapters ago will reveal that mx will receive the maximum value of index or count. In like manner, the MIN macro will result in mn receiving the minimum value of index or count. When defining a macro, it is imperative that there is no space between the macro name and the opening parenthesis. If there is a space, the compiler cannot determine that it is a macro, but will handle it like a simple substitution define statement. The results are then printed out in line 17. There are a lot of seemingly extra parentheses in the macro definition but they are not extra, they are essential. We will discuss the extra parentheses in our next example program. Be sure to compile and execute DEFINE.C before going on to the next program. Page 6-2 Chapter 6 - Defines and Macros LET'S LOOK AT A WRONG MACRO ____________________________________________________________ Load the file named MACRO.C and display it on ============= your screen for a better look at a macro and MACRO.C its use. Line 4 defines a macro named WRONG ============= that appears to get the cube of A, and indeed it does in some cases, but it fails miserably in others. The second macro named CUBE actually does get the cube in all cases. Consider the program itself where the CUBE of i+offset is calculated. If i is 1, which it is the first time through, then we will be looking for the cube of 1+5 = 6, which will result in 216. When using CUBE, we group the values like this, (1+5)*(1+5)*(1+5) = 6*6*6 = 216. However, when we use WRONG, we group them as 1+5*1+5*1+5 = 1+5+5+5 = 16 which is a wrong answer. The parentheses are therefore required to properly group the variables together. It should be clear to you that either CUBE or WRONG would arrive at a correct answer for a single term replacement such as we did in the last program. The correct values of the cube and the square of the numbers are printed out as well as the wrong values for your inspection. In line 7 we define the macro ADD_WRONG according to the above rules but we still have a problem when we try to use the macro in line 25 and 26. In line 26 when we say we want the program to calculate 5*ADD_WRONG(i) with i = 1, we get the result 5*1 + 1 which evaluates to 5 + 1 or 6, and this is most assuredly not what we had in mind. We really wanted the result to be 5*(1 + 1) = 5*2 = 10 which is the answer we get when we use the macro named ADD_RIGHT, because of the extra parentheses in the definition given in line 8. A little time spent studying the program and the result will be worth your effort in understanding how to use macros. In order to prevent the above problems, most experienced C programmers include parentheses around each variable in a macro and additional parentheses around the entire expression. The remainder of the program is simple and will be left to your inspection and understanding. WHAT IS AN ENUMERATION VARIABLE? ____________________________________________________________ Load and display the program named ENUM.C for ============ an example of how to use the enum type ENUM.C variable. Line 6 contains the first enum ============ type variable named result which is a variable which can take on any of the values contained within the parentheses. Actually the variable Page 6-3 Chapter 6 - Defines and Macros result is an int type variable but can be assigned any of the values defined for it. The names within the parentheses are int type constants and can be used anywhere it is legal to use an int type constant. The constant win is assigned the value of 0, tie the value 1, bye the value 2, etc. In use, the variable named result is used just like any int variable would be used as can be seen by its use in the program. The enum type of variable is intended to be used by you, the programmer, as a coding aid since you can use a constant named mon for control structures rather than the meaningless (at least to you) value of 1. Notice that days is assigned the values of days of the week in the remainder of the program. If you were to use a switch statement, it would be much more meaningful to use the labels sun, mon, etc, rather than the more awkward 0, 1, 2, etc. PROGRAMMING EXERCISE ____________________________________________________________ 1. Write a program to count from 7 to -5 by counting down. Use #define statements to define the limits. (Hint, you will need to use a decrementing variable in the third part of the for loop control. Page 6-4