📄 chapter2.html
字号:
number.<p>Conversions take place across assignments; the value of the right side isconverted to the type of the left, which is the type of the result.<p>A character is converted to an integer, either by sign extension or not, asdescribed above.<p>Longer integers are converted to shorter ones or to <tt>char</tt>s by droppingthe excess high-order bits. Thus in<pre> int i; char c; i = c; c = i;</pre>the value of <tt>c</tt> is unchanged. This is true whether or not sign extensionis involved. Reversing the order of assignments might lose information,however.<p>If <tt>x</tt> is <tt>float</tt> and <tt>i</tt> is <tt>int</tt>, then <tt>x = i</tt>and <tt>i = x</tt> both cause conversions; <tt>float</tt> to <tt>int</tt> causestruncation of any fractional part. When a <tt>double</tt> is converted to <tt>float</tt>,whether the value is rounded or truncated is implementation dependent.<p>Since an argument of a function call is an expression, type conversion alsotakes place when arguments are passed to functions. In the absence of afunction prototype, <tt>char</tt> and <tt>short</tt> become int, and <tt>float</tt>becomes <tt>double</tt>. This is why we have declared function arguments to be<tt>int</tt> and <tt>double</tt> even when the function is called with <tt>char</tt>and <tt>float</tt>.<p>Finally, explicit type conversions can be forced (``coerced'') in anyexpression, with a unary operator called a <tt>cast</tt>. In the construction<p> (<em>type name</em>) <em>expression</em><p>the <em>expression</em> is converted to the named type by the conversion rulesabove. The precise meaning of a cast is as if the <em>expression</em> wereassigned to a variable of the specified type, which is then used in place ofthe whole construction. For example, the library routine <tt>sqrt</tt> expectsa <tt>double</tt> argument, and will produce nonsense if inadvertently handledsomething else. (<tt>sqrt</tt> is declared in <tt><math.h></tt>.) So if<tt>n</tt> is an integer, we can use<pre> sqrt((double) n)</pre>to convert the value of <tt>n</tt> to <tt> double</tt> before passing it to<tt>sqrt</tt>. Note that the cast produces the <em>value</em> of <tt>n</tt> in theproper type; <tt>n</tt> itself is not altered. The cast operator has the samehigh precedence as other unary operators, as summarized in the table at theend of this chapter.<p>If arguments are declared by a function prototype, as the normally should be,the declaration causes automatic coercion of any arguments when the functionis called. Thus, given a function prototype for <tt>sqrt</tt>:<pre> double sqrt(double)</pre>the call<pre> root2 = sqrt(2)</pre>coerces the integer <tt>2</tt> into the <tt>double</tt> value <tt>2.0</tt>without any need for a cast.<p>The standard library includes a portable implementation of apseudo-random number generator and a function for initializing the seed; theformer illustrates a cast:<pre> unsigned long int next = 1; /* rand: return pseudo-random integer on 0..32767 */ int rand(void) { next = next * 1103515245 + 12345; return (unsigned int)(next/65536) % 32768; } /* srand: set seed for rand() */ void srand(unsigned int seed) { next = seed; }</pre><strong>Exercise 2-3.</strong> Write a function <tt>htoi(s)</tt>, which converts a stringof hexadecimal digits (including an optional <tt>0x</tt> or <tt>0X</tt>) into itsequivalent integer value. The allowable digits are <tt>0</tt> through <tt>9</tt>,<tt>a</tt> through <tt>f</tt>, and <tt>A</tt> through <tt>F</tt>.<h2><a name="s2.8">2.8 Increment and Decrement Operators</a></h2>C provides two unusual operators for incrementing and decrementing variables.The increment operator <tt>++</tt> adds 1 to its operand, while the decrementoperator <tt>--</tt> subtracts 1. We have frequently used <tt>++</tt> to incrementvariables, as in<pre> if (c == '\n') ++nl;</pre>The unusual aspect is that <tt>++</tt> and <tt>--</tt> may be used either as prefixoperators (before the variable, as in <tt>++n</tt>), or postfix operators (afterthe variable: <tt>n++</tt>). In both cases, the effect is to increment <tt>n</tt>.But the expression <tt>++n</tt> increments <tt>n</tt> <em>before</em> its value isused, while <tt>n++</tt> increments <tt>n</tt> <em>after</em> its value has been used.This means that in a context where the value is being used, not just theeffect, <tt>++n</tt> and <tt>n++</tt> are different. If <tt>n</tt> is 5, then<pre> x = n++;</pre>sets <tt>x</tt> to 5, but<pre> x = ++n;</pre>sets <tt>x</tt> to 6. In both cases, <tt>n</tt> becomes 6. The increment anddecrement operators can only be applied to variables; an expression like<tt>(i+j)++</tt> is illegal.<p>In a context where no value is wanted, just the incrementing effect, as in<pre> if (c == '\n') nl++;</pre>prefix and postfix are the same. But there are situations where one or theother is specifically called for. For instance, consider the function<tt>squeeze(s,c)</tt>, which removes all occurrences of the character<tt>c</tt> from the string <tt>s</tt>.<pre> /* squeeze: delete all c from s */ void squeeze(char s[], int c) { int i, j; for (i = j = 0; s[i] != '\0'; i++) if (s[i] != c) s[j++] = s[i]; s[j] = '\0'; }</pre>Each time a non-<tt>c</tt> occurs, it is copied into the current <tt>j</tt>position, and only then is <tt>j</tt> incremented to be ready for the nextcharacter. This is exactly equivalent to<pre> if (s[i] != c) { s[j] = s[i]; j++; }</pre>Another example of a similar construction comes from the <tt>getline</tt>function that we wrote in <a href="chapter1.html">Chapter 1</a>, where we can replace<pre> if (c == '\n') { s[i] = c; ++i; }</pre>by the more compact<pre> if (c == '\n') s[i++] = c;</pre>As a third example, consider the standard function <tt>strcat(s,t)</tt>, whichconcatenates the string <tt>t</tt> to the end of string <tt>s</tt>. <tt>strcat</tt>assumes that there is enough space in <tt>s</tt> to hold the combination. As wehave written it, <tt>strcat</tt> returns no value; the standard library versionreturns a pointer to the resulting string.<pre> /* strcat: concatenate t to end of s; s must be big enough */ void strcat(char s[], char t[]) { int i, j; i = j = 0; while (s[i] != '\0') /* find end of s */ i++; while ((s[i++] = t[j++]) != '\0') /* copy t */ ; }</pre>As each member is copied from <tt>t</tt> to <tt>s</tt>, the postfix <tt>++</tt> isapplied to both <tt>i</tt> and <tt>j</tt> to make sure that they are in positionfor the next pass through the loop.<p><strong>Exercise 2-4.</strong> Write an alternative version of <tt>squeeze(s1,s2)</tt> thatdeletes each character in <tt>s1</tt> that matches any character in the <em>string</em> <tt>s2</tt>.<p><strong>Exercise 2-5.</strong> Write the function <tt>any(s1,s2)</tt>, which returns thefirst location in a string <tt>s1</tt> where any character from the string<tt>s2</tt> occurs, or <tt>-1</tt> if <tt>s1</tt> contains no characters from <tt>s2</tt>.(The standard library function <tt>strpbrk</tt> does the same job but returns apointer to the location.)<h2><a name="s2.9">2.9 Bitwise Operators</a></h2>C provides six operators for bit manipulation; these may only be applied tointegral operands, that is, <tt>char</tt>, <tt>short</tt>, <tt>int</tt>, and<tt>long</tt>, whether signed or unsigned.<p><table align="center"><td><tt>&</tt></td> <td>bitwise AND</td><tr><td><tt>|</tt></td> <td>bitwise inclusive OR</td><tr><td><tt>^</tt></td><td>bitwise exclusive OR</td><tr><td><tt><<</tt> </td><td>left shift</td><tr><td><tt>>></tt></td><td>right shift</td><tr><td><tt>~</tt></td> <td>one's complement (unary)</td></table><p>The bitwise AND operator <tt>&</tt> is often used to mask off some set of bits,for example<pre> n = n & 0177;</pre>sets to zero all but the low-order 7 bits of <tt>n</tt>.<p>The bitwise OR operator <tt>|</tt> is used to turn bits on:<pre> x = x | SET_ON;</pre>sets to one in <tt>x</tt> the bits that are set to one in <tt>SET_ON</tt>.<p>The bitwise exclusive OR operator <tt>^</tt> sets a one in each bit positionwhere its operands have different bits, and zero where they are the same.<p>One must distinguish the bitwise operators <tt>&</tt> and <tt>|</tt> from thelogical operators <tt>&&</tt> and <tt>||</tt>, which imply left-to-rightevaluation of a truth value. For example, if <tt>x</tt> is 1 and <tt>y</tt> is 2,then <tt>x & y</tt> is zero while <tt>x && y</tt> is one.<p>The shift operators <tt><<</tt> and <tt>>></tt> perform left and right shifts oftheir left operand by the number of bit positions given by the right operand,which must be non-negative. Thus <tt>x << 2</tt> shifts the value of<tt>x</tt> by two positions, filling vacated bits with zero; this is equivalent tomultiplication by 4. Right shifting an <tt>unsigned</tt> quantity always fitsthe vacated bits with zero. Right shifting a signed quantity will fill withbit signs (``arithmetic shift'') on some machines and with 0-bits (``logicalshift'') on others.<p>The unary operator <tt>~</tt> yields the one's complement of an integer; thatis, it converts each 1-bit into a 0-bit and vice versa. For example<pre> x = x & ~077</pre>sets the last six bits of <tt>x</tt> to zero. Note that <tt>x & ~077</tt> isindependent of word length, and is thus preferable to, for example,<tt>x & 0177700</tt>, which assumes that <tt>x</tt> is a 16-bit quantity. Theportable form involves no extra cost, since <tt>~077</tt> is a constantexpression that can be evaluated at compile time.<p>As an illustration of some of the bit operators, consider the function<tt>getbits(x,p,n)</tt> that returns the (right adjusted) <tt>n</tt>-bitfield of <tt>x</tt> that begins at position <tt>p</tt>. We assume that bitposition 0 is at the right end and that <tt>n</tt> and <tt>p</tt> aresensible positive values. For example, <tt>getbits(x,4,3)</tt> returns thethree bits in positions 4, 3 and 2, right-adjusted.<pre> /* getbits: get n bits from position p */ unsigned getbits(unsigned x, int p, int n) { return (x >> (p+1-n)) & ~(~0 << n); }</pre>The expression <tt>x >> (p+1-n)</tt> moves the desired field to the right endof the word. <tt>~0</tt> is all 1-bits; shifting it left <tt>n</tt> positions with<tt>~0<<n</tt> places zeros in the rightmost <tt>n</tt> bits; complementing thatwith <tt>~</tt> makes a mask with ones in the rightmost <tt>n</tt> bits.<p><strong>Exercise 2-6.</strong> Write a function <tt>setbits(x,p,n,y)</tt> that returns<tt>x</tt> with the <tt>n</tt> bits that begin at position <tt>p</tt> set to the rightmost
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -