Commit | Line | Data |
---|---|---|
b3f974bf BK |
1 | .NH |
2 | Bit Operators | |
3 | .PP | |
4 | C has several operators for logical bit-operations. | |
5 | For example, | |
6 | .E1 | |
7 | x = x & 0177; | |
8 | .E2 | |
9 | forms the bit-wise | |
10 | .UC AND | |
11 | of | |
12 | .UL x | |
13 | and 0177, | |
14 | effectively retaining only the last seven bits of | |
15 | .UL x\*. | |
16 | Other operators are | |
17 | .E1 | |
18 | .ft R | |
19 | \(or inclusive OR | |
20 | ^ (circumflex) exclusive OR | |
21 | .tr+~ | |
22 | + (tilde) 1's complement | |
23 | .tr++ | |
24 | ! logical NOT | |
25 | << left shift (as in x<<2) | |
26 | >> right shift (arithmetic on PDP\(hy11; logical on H6070, IBM360) | |
27 | .E2 | |
28 | .NH | |
29 | Assignment Operators | |
30 | .PP | |
31 | An unusual feature of C | |
32 | is that the normal binary operators like | |
33 | `+', `\(mi', etc. | |
34 | can be combined with the assignment operator `=' | |
35 | to form new assignment operators. | |
36 | For example, | |
37 | .E1 | |
38 | x =- 10; | |
39 | .E2 | |
40 | uses the assignment operator `=\(mi' to decrement | |
41 | .UL x | |
42 | by 10, | |
43 | and | |
44 | .E1 | |
45 | x =& 0177 | |
46 | .E2 | |
47 | forms the | |
48 | .UC AND | |
49 | of | |
50 | .UL x | |
51 | and 0177. | |
52 | This convention is a useful notational shortcut, | |
53 | particularly if | |
54 | .UL x | |
55 | is a complicated expression. | |
56 | The classic example is summing an array: | |
57 | .E1 | |
58 | for( sum=i=0; i<n; i\*+ ) | |
59 | sum =+ array[i]; | |
60 | .E2 | |
61 | But the spaces around the operator are critical! | |
62 | For instance, | |
63 | .E1 | |
64 | x = -10; | |
65 | .E2 | |
66 | sets | |
67 | .UL x | |
68 | to | |
69 | \(mi10, while | |
70 | .E1 | |
71 | x =- 10; | |
72 | .E2 | |
73 | subtracts 10 from | |
74 | .UL x\*. | |
75 | When no space is present, | |
76 | .E1 | |
77 | x=-10; | |
78 | .E2 | |
79 | also decreases | |
80 | .UL x | |
81 | by 10. | |
82 | This is quite contrary to the experience of most programmers. | |
83 | In particular, watch out for things like | |
84 | .E1 | |
85 | c=\**s\*+; | |
86 | y=&x[0]; | |
87 | .E2 | |
88 | both of which are almost certainly not what you wanted. | |
89 | Newer versions of various compilers are courteous enough to warn you about the ambiguity. | |
90 | .PP | |
91 | Because all other operators in an expression are evaluated | |
92 | before the assignment operator, | |
93 | the order of evaluation should be watched carefully: | |
94 | .E1 | |
95 | x = x<<y | z; | |
96 | .E2 | |
97 | means | |
98 | ``shift | |
99 | .UL x | |
100 | left | |
101 | .UL y | |
102 | places, | |
103 | then | |
104 | .UC OR | |
105 | with | |
106 | .UL z, | |
107 | and store in | |
108 | .UL x\*.'' | |
109 | But | |
110 | .E1 | |
111 | x =<< y | z; | |
112 | .E2 | |
113 | means | |
114 | ``shift | |
115 | .UL x | |
116 | left by | |
117 | .UL y|z | |
118 | places'', | |
119 | which is rather different. | |
120 | .NH | |
121 | Floating Point | |
122 | .PP | |
123 | We've skipped over floating point so far, | |
124 | and the treatment here will be hasty. | |
125 | C has single and double precision numbers | |
126 | (where the precision depends on the machine at hand). | |
127 | For example, | |
128 | .E1 | |
129 | double sum; | |
130 | float avg, y[10]; | |
131 | sum = 0\*.0; | |
132 | for( i=0; i<n; i\*+ ) | |
133 | sum =+ y[i]; | |
134 | avg = sum/n; | |
135 | .E2 | |
136 | forms the sum and average of the array | |
137 | .UL y\*. | |
138 | .PP | |
139 | All floating arithmetic is done in double precision. | |
140 | Mixed mode arithmetic is legal; | |
141 | if an arithmetic operator in an expression | |
142 | has both operands | |
143 | .UL int | |
144 | or | |
145 | .UL char, | |
146 | the arithmetic done is integer, but | |
147 | if one operand is | |
148 | .UL int | |
149 | or | |
150 | .UL char | |
151 | and the other is | |
152 | .UL float | |
153 | or | |
154 | .UL double, | |
155 | both operands are converted to | |
156 | .UL double\*. | |
157 | Thus if | |
158 | .UL i | |
159 | and | |
160 | .UL j | |
161 | are | |
162 | .UL int | |
163 | and | |
164 | .UL x | |
165 | is | |
166 | .UL float, | |
167 | .E1 | |
168 | (x+i)/j converts i and j to float | |
169 | x + i/j does i/j integer, then converts | |
170 | .E2 | |
171 | Type conversion | |
172 | may be made by assignment; | |
173 | for instance, | |
174 | .E1 | |
175 | int m, n; | |
176 | float x, y; | |
177 | m = x; | |
178 | y = n; | |
179 | .E2 | |
180 | converts | |
181 | .UL x | |
182 | to integer | |
183 | (truncating toward zero), | |
184 | and | |
185 | .UL n | |
186 | to floating point. | |
187 | .PP | |
188 | Floating constants are just like those in Fortran or PL/I, | |
189 | except that the exponent letter is `e' instead of `E'. | |
190 | Thus: | |
191 | .E1 | |
192 | pi = 3\*.14159; | |
193 | large = 1\*.23456789e10; | |
194 | .E2 | |
195 | .PP | |
196 | .UL printf | |
197 | will format floating point numbers: | |
198 | .UL ``%w\*.df'' | |
199 | in the format string will print the corresponding variable | |
200 | in a field | |
201 | .UL w | |
202 | digits wide, with | |
203 | .UL d | |
204 | decimal places. | |
205 | An | |
206 | .UL e | |
207 | instead of an | |
208 | .UL f | |
209 | will produce exponential notation. | |
210 | .NH | |
211 | Horrors! goto's and labels | |
212 | .PP | |
213 | C has | |
214 | a | |
215 | .UL goto | |
216 | statement and labels, so you can branch about | |
217 | the way you used to. | |
218 | But most of the time | |
219 | .UL goto's | |
220 | aren't needed. | |
221 | (How many have we used up to this point?) | |
222 | The code can almost always be more clearly expressed by | |
223 | .UL for/while, | |
224 | .UL if/else, | |
225 | and compound statements. | |
226 | .PP | |
227 | One use of | |
228 | .UL goto's | |
229 | with some legitimacy is in a program | |
230 | which | |
231 | contains a long loop, | |
232 | where a | |
233 | .UL while(1) | |
234 | would be too extended. | |
235 | Then you might write | |
236 | .E1 | |
237 | mainloop: | |
238 | \*.\*.\*. | |
239 | goto mainloop; | |
240 | .E2 | |
241 | Another use is to implement a | |
242 | .UL break | |
243 | out of more than one level of | |
244 | .UL for | |
245 | or | |
246 | .UL while\*. | |
247 | .UL goto's | |
248 | can only branch to labels within the same function. | |
249 | .NH | |
250 | Acknowledgements | |
251 | .PP | |
252 | I am indebted to a veritable host of readers who made | |
253 | valuable criticisms on several drafts of this tutorial. | |
254 | They ranged in experience from complete beginners | |
255 | through several implementors of C compilers | |
256 | to the C language designer himself. | |
257 | Needless to say, this is a wide enough spectrum of opinion | |
258 | that no one is satisfied (including me); | |
259 | comments and suggestions are still welcome, | |
260 | so that some future version might be improved. |