⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chapter2.html

📁 Kernighan and Ritchie - The C Programming Language c程序设计语言(第二版)称作是C语言学习的圣经
💻 HTML
📖 第 1 页 / 共 4 页
字号:
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>&nbsp;&nbsp;(<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>&lt;math.h&gt;</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>&lt;&lt;</tt>&nbsp;&nbsp;</td><td>left shift</td><tr><td><tt>&gt;&gt;</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>&lt;&lt;</tt> and <tt>&gt;&gt;</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 &lt;&lt; 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 &gt;&gt; (p+1-n)) & ~(~0 &lt;&lt; n);   }</pre>The expression <tt>x &gt;&gt; (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&lt;&lt;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 + -