This section lies somewhat outside the main development of the book. You might wish to omit it on a first reading.
There are a handful more preprocessor commands which can largely be ignored by the beginner. They are commonly used in"include"files to make sure that things are not defined twice.
NOTE : ‘true’ has any non zero value in C. ‘false’ is zero.
#undef This undefines a macro, leaving the name free.
#if This is followed by some expression on the same line. It allows
Example 75
used to say: only compile the code between ‘#if’ and ‘#endif’ if the value following ‘#if’ is true, else leave out that code alto- gether. This is different from not executing code—the code will not even be compiled.
#ifdef This is followed by a macro name. If that macro is defined then this is true.
#ifndef This is followed by a macro name. If that name is not defined then this is true.
#else This is part of an#if,#ifdef,#ifndefpreprocessor statement.
#endif This marks the end of a preprocessor statement.
#line Has the form:
#lineconstant ‘filename’
This is for debugging mainly. This statement causes the com- piler to believe that the next line is line number (constant) and is part of the file (filename).
#error This is a part of the proposed ANSI standard. It is intended for debugging. It forces the compiler to abort compilation.
12.6 Example
/***********************************************************/ /* To compile or not to compile */ /***********************************************************/
#define SOMEDEFINITION 6546
#define CHOICE 1 /* Choose this before compiling */
/***********************************************************/
#if (CHOICE == 1)
#define OPTIONSTRING "The programmer selected this" #define DITTO "instead of .... "
#else
#define OPTIONSTRING "The alternative" #define DITTO "i.e. This! "
#endif
/***********************************************************/
#define WHATEVER "Something was defined!"
#else
#define WHATEVER "Nothing was defined"
#endif /************************************************************/ main () { printf (OPTIONSTRING); printf (DITTO); }
12.7 Questions
1. Define a macro called "birthday"which describes the day of the month upon which your birthday falls.
2. Write an instruction to the preprocessor to include to maths library ‘math.h’.
3. A macro is always a number. True or false? 4. A macro is always a constant. True or false?
Pointers 77
13 Pointers
Making maps of data.
You have a map (a plan) of the computer’s memory. You need to find that essential piece of information which is stored at some unknown location. How will you find it? You need a pointer!
A pointers is a special type of variable which holds the address or location of another variable. Pointers point to these locations by keeping a record of the spot at which they were stored. Pointers to variables are found by recording the address at which a variable is stored. It is always possible to find the address of a piece of storage in C using the special ‘&’ operator. For instance: if location were a float type variable, it would be easy to find a pointer to it called location_ptr.
float location;
float *location_ptr,*address;
location_ptr = &(location);
or
address = &(location);
The declarations of pointers look a little strange at first. The star ‘*’ symbol which stands in front of the variable name is C’s way of declaring that variable to be a pointer. The four lines above make two identical pointers to a floating point variable called location, one of them is called location_ ptr and the other is called address. The point is that a pointer is just a place to keep a record of the address of a variable, so they are really the same thing.
A pointer is a bundle of information that has two parts. One part is the address of the beginning of the segment of memory that holds whatever is pointed to. The other part is the type of value that the pointer points to the beginning of. This tells the computer how much of the memory after the beginning to read and how to interpret it. Thus, if the pointer is of a type int, the segment of memory returned will be four bytes long (32 bits) and be interpreted as an integer. In the case of a function, the type is the type of value that the function will return, although the address is the address of the beginning of the function executable.
If, like some modern day programmers, you believe in sanctity of high level languages, it is probably a source of wonder why anyone Would ever want to know the address of these variables. Having gone to the trouble to design a high level language, like C, in which variables can be given elegant and meaningful names: it seems like a step in the backward direction to
want to be able to find out the exact number of the memory location at which it is stored! The whole point of variables, after all, is that it is not necessary to know exactly where information is really stored. This is not quite fair though. It is certainly rare indeed when we should want to know the actual number of the memory location at which something is stored. That would really make the idea of a high level language a bit pointless. The idea behind pointers is that a high level programmer can now find out the exact location of a variable without ever having to know the actual number involved. Remember:
A pointer is a variable which holds the address of the storage location for another given variable.
C provides two operators ‘&’ and ‘*’ which allow pointers to be used in many versatile ways.
13.1 ‘&’ and ‘*’
The ‘&’ and ‘*’ operators have already been used once to hand back values to variable parameters, See Section 10.2 [Value parameters], page 52. They can be read in a program to have the following meanings:
& The address of...
* The contents of the address held in... Another way of saying the second of these is:
‘*’ The contents of the location pointed to by...
This reinforces the idea that pointers reach out an imaginary hand and point to some location in the memory and it is more usual to speak of pointers in this way. The two operators ‘*’ and ‘&’ are always written in front of a variable, clinging on, so that they refer, without doubt, to that one variable. For instance:
‘&x’ The address at which the variable ‘x’ is stored.
‘*ptr’ The contents of the variable which is pointed to by ptr.
The following example might help to clarify the way in which they are used:
int somevar; /* 1 */ int *ptr_to_somevar; /* 2 */ somevar = 42; /* 3 */ ptr_to_somevar = &(somevar); /* 4 */ printf ("%d",*ptr_to_somevar); /* 5 */ *ptr_to_somevar = 56; /* 6 */
Uses for Pointers 79
1. Declare aninttype variable called somevar.
2. Declare a pointer to an int type calledptr_to_somevar. The ‘*’ which stands in front of ptr_to_somevar is the way C declares ptr_to_ somevar as a pointer to an integer, rather than an integer.
3. Let somevartake the value 42.
4. This gives a value to ptr_to_somevar. The value is the address of the variable somevar. Notice that only at this stage does is become a pointer to the particular variablesomevar. Before this, its fate is quite open. The declaration (2) merely makes it a pointer which can point to any integer variable which is around.
5. Print out"the contents of the location pointed to byptr_to_somevar"
in other words somevar itself. So this will be just 42.
6. Let the contents of the location pointed to by ptr_to_somevarbe 56. This is the same as the more direct statement:
somevar = 56;