* better
[mascara-docs.git] / lang / C / the.ansi.c.programming.language / notes.accompany.ansi.c / sx8d.html
blob5bfb06e5420c056608e1c018fe13818cb06c3d48
1 <!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
2 <!-- This collection of hypertext pages is Copyright 1995, 1996 by Steve Summit. -->
3 <!-- This material may be freely redistributed and used -->
4 <!-- but may not be republished or sold without permission. -->
5 <html>
6 <head>
7 <link rev="owner" href="mailto:scs@eskimo.com">
8 <link rev="made" href="mailto:scs@eskimo.com">
9 <title>section 5.4: Address Arithmetic</title>
10 <link href="sx8c.html" rev=precedes>
11 <link href="sx8e.html" rel=precedes>
12 <link href="sx8.html" rev=subdocument>
13 </head>
14 <body>
15 <H2>section 5.4: Address Arithmetic</H2>
17 <p>This section is going to get pretty hairy.
18 Some of it talks about things we've already seen
19 (adding integers to pointers);
20 some of it talks about things we need to learn
21 (comparing and subtracting pointers);
22 and some of it talks about a rather sophisticated example
23 (a storage allocator).
24 Don't worry if you can't follow all the details of the storage allocator,
25 but do read along so that you can pick up the other new points.
26 (In other words,
27 make sure you read from
28 ``Zero is the sole exception''
29 in the middle of page 102
31 ``that is, the string length''
32 on page 103,
33 and also the last paragraph on page 103.)
34 </p><p>What is a storage allocator for?
35 So far,
36 we've used pointers to point to existing variables and arrays,
37 which the compiler allocated for us.
38 But eventually,
39 we may want to allocate data structures
40 (arrays, and others we haven't seen yet)
41 of a size which we don't know at compile time.
42 Earlier,
43 we spoke briefly about a hypothetical inventory-management system,
44 which recorded information about each part stored in a warehouse.
45 How many different parts could there be?
46 If we used fixed-size arrays,
47 there would be a fixed upper limit
48 on the number of parts we could enter into the system,
49 and we'd be annoyed if that limit were reached.
50 A better solution is not to allocate a fixed array at compile time,
51 but rather to use a run-time storage allocator to allocate
52 memory for the data structures used to describe each part.
53 That way, the number of parts which the system can hold
54 is limited only by available memory,
55 not on any static limit built into the program.
56 Using a storage allocator to allocate memory at run time
57 in this way
58 is called <dfn>dynamic allocation</dfn>.
59 </p><p>However,
60 dynamic memory allocation is where C programming can really get tricky,
61 because you the programmer are responsible for most aspects of it,
62 and there are plenty of things you can do wrong
63 (e.g. not allocate quite enough memory,
64 accidentally keep using it after you deallocate it,
65 have random invalid pointers pointing everywhere, etc.).
66 Therefore,
67 we won't be talking about dynamic allocation for a while,
68 which is why you can skim over the storage allocator in this section for now.
69 </p><p>page 102
70 </p><p>The first new piece of information in this section
71 (which you'll need to remember
72 even if you're not following the details of the storage allocator example)
73 is the introduction of the ``null pointer.''
74 </p><p>So far, all of our pointers have pointed somewhere,
75 and we've cautioned about pointers which don't.
76 To help us distinguish between pointers which point somewhere
77 and pointers which don't,
78 there is a single, special pointer value
79 we can use,
80 which is guaranteed
81 not to point anywhere.
82 When a pointer doesn't point anywhere,
83 we can set it to this value,
84 to make explicit the fact that it doesn't point anywhere.
85 </p><p>This special pointer value is called the <dfn>null pointer</dfn>.
86 The way to set a pointer to this value is to use a constant 0:
87 <pre> int *ip = 0;
88 </pre>The 0 is just a shorthand;
89 it does <em>not</em> necessarily mean machine address 0.
90 To make it clear that we're talking about the null pointer
91 and not the integer 0,
92 we often use a macro definition like
93 <pre> #define NULL 0
94 </pre>so that we can say things like
95 <pre> int *ip = NULL;
96 </pre>(If you've used Pascal or LISP,
97 the <TT>nil</TT> pointer in those languages is analogous.)
98 </p><p>In fact,
99 the above #definition of <TT>NULL</TT> has been placed in the
100 standard header file <TT>&lt;stdio.h&gt;</TT> for us
101 (and in several other standard header files as well),
102 so we don't even need to <TT>#define</TT> it.
103 I agree completely with the authors
104 that using <TT>NULL</TT> instead of 0
105 makes it more clear that we're talking about a null pointer,
106 so I'll always be using <TT>NULL</TT>, too.
107 </p><p>Just as we can set a pointer to <TT>NULL</TT>,
108 we can also test a pointer to see if it's <TT>NULL</TT>.
109 The code
110 <pre> if(p != NULL)
111 *p = 0;
112 else printf("p doesn't point anywhere\n");
113 </pre>tests <TT>p</TT> to see if it's non-<TT>NULL</TT>.
114 If it's not <TT>NULL</TT>,
115 it assumes that it points somewhere valid,
116 and writes a 0 there.
117 Otherwise
118 (i.e. if <TT>p</TT> is the null pointer)
119 the code complains.
120 </p><p>Though we can use null pointers as markers to remind ourselves
121 of which of our pointers don't point anywhere,
122 it's up to us to do so.
123 It is <em>not</em> guaranteed that all uninitialized pointer
124 variables
125 (which obviously don't point anywhere)
126 are initialized to <TT>NULL</TT>,
128 if we want to use the null pointer convention to remind ourselves,
129 we'd best explicitly initialize all
130 unused
131 pointers to <TT>NULL</TT>.
132 Furthermore,
133 there is no general mechanism that automatically checks
134 whether a pointer is non-null before we use it.
135 If we think that a pointer might not point anywhere,
136 and if we're using the convention that pointers that don't
137 point anywhere are set to <TT>NULL</TT>,
138 it's up to us to compare the pointer to <TT>NULL</TT>
139 to decide whether it's safe to
142 </p><p>The next new piece of information in this section
143 (which we've already alluded to)
144 is pointer comparison.
145 You can compare two pointers for equality or inequality
146 (<TT>==</TT> or <TT>!=</TT>):
147 they're equal if they point to the same place or are both null pointers;
148 they're unequal if they point to different places,
149 or if one points somewhere and one is a null pointer.
151 two pointers point into the same array,
152 the relational comparisons
153 <TT>&lt;</TT>, <TT>&lt;=</TT>, <TT>&gt;</TT>, and <TT>&gt;=</TT>
154 can also be used.
155 </p><p>page 103
156 </p><p>The sentences
157 <blockquote>...<TT>n</TT> is scaled according to the size of the objects <TT>p</TT> points to,
158 which is determined by the declaration of <TT>p</TT>.
159 If an <TT>int</TT> is four bytes,
160 for example,
161 the <TT>int</TT> will be scaled by four.
162 </blockquote>say something we've seen already,
163 but may only confuse the issue.
164 We've said informally that in the code
165 <pre> int a[10];
166 int *pa = &amp;a[0];
167 *(pa+1) = 1;
168 </pre><TT>pa</TT> contains the ``address'' of the <TT>int</TT> object <TT>a[0]</TT>,
169 but we've discouraged thinking about this address
170 as an actual machine memory address.
171 We've said that the expression <TT>pa+1</TT>
172 moves to the next <TT>int</TT> in the array
173 (in this case, <TT>a[1]</TT>).
174 Thinking at this abstract level,
175 we don't even need to worry about any
176 ``scaling by the size of the objects pointed to.''
177 </p><p>If we do look at a lower, machine level of addressing,
178 we may learn that an <TT>int</TT> occupies some number of bytes
179 (usually two or four),
180 such that when we add 1 to a pointer-to-<TT>int</TT>,
181 the machine address is actually increased by 2 or 4.
182 If you like to consider the situation from this angle,
183 you're welcome to,
184 but if you don't,
185 you certainly don't have to.
186 If you do start thinking about machine addresses and sizes,
187 make extra sure that you remember that C <em>does</em> do the necessary
188 scaling for you.
189 Don't write something like
190 <pre> int a[10];
191 int *pa = &amp;a[0];
192 *(pa+sizeof(int)) = 1;
193 </pre>where <TT>sizeof(int)</TT> is the size of an <TT>int</TT> in bytes,
194 and expect it to access <TT>a[1]</TT>.
195 </p><p>Since adding an <TT>int</TT> to a pointer gives us another pointer:
196 <pre> int a[10];
197 int *pa1 = &amp;a[0];
198 int *pa2 = pa1 + 5;
199 </pre>we might wonder if we can rearrange the expression
200 <pre> pa2 = pa1 + 5
201 </pre>to get
202 <pre> pa2 - pa1 5
203 </pre>(where this is no longer a C assignment,
204 we're just wondering if we can subtract <TT>pa1</TT> from <TT>pa2</TT>,
205 and what the result might be).
206 The answer is yes:
207 just as you can compare two pointers which point into the same array,
208 you can subtract them,
209 and the result is,
210 naturally enough,
211 the distance between them,
212 in cells or elements.
213 </p><p>(In the large parenthetical statement in the middle of the page,
214 don't worry too much about
215 <TT>ptrdiff_t</TT>, <TT>size_t</TT>, and <TT>sizeof</TT>.)
216 </p><hr>
218 Read sequentially:
219 <a href="sx8c.html" rev=precedes>prev</a>
220 <a href="sx8e.html" rel=precedes>next</a>
221 <a href="sx8.html" rev=subdocument>up</a>
222 <a href="top.html">top</a>
223 </p>
225 This page by <a href="http://www.eskimo.com/~scs/">Steve Summit</a>
226 // <a href="copyright.html">Copyright</a> 1995, 1996
227 // <a href="mailto:scs@eskimo.com">mail feedback</a>
228 </p>
229 </body>
230 </html>