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

📄 chapter2.html

📁 Kernighan and Ritchie - The C Programming Language c程序设计语言(第二版)称作是C语言学习的圣经
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<tt>n</tt> bits of <tt>y</tt>, leaving the other bits unchanged.<p><strong>Exercise 2-7.</strong> Write a function <tt>invert(x,p,n)</tt> that returns <tt>x</tt>with the <tt>n</tt> bits that begin at position <tt>p</tt> inverted (i.e., 1changed into 0 and vice versa), leaving the others unchanged.<p><strong>Exercise 2-8.</strong> Write a function <tt>rightrot(x,n)</tt> that returns thevalue of the integer <tt>x</tt> rotated to the right by <tt>n</tt> positions.<h2><a name="s2.10">2.10 Assignment Operators and Expressions</a></h2>An expression such as<pre>   i = i + 2</pre>in which the variable on the left side is repeated immediately on the right,can be written in the compressed form<pre>   i += 2</pre>The operator <tt>+=</tt> is called an <em>assignment operator</em>.<p>Most binary operators (operators like <tt>+</tt> that have a left and rightoperand) have a corresponding assignment operator <em>op</em><tt>=</tt>, where<em>op</em> is one of<pre>   +   -   *   /   %   &lt;&lt;   &gt;&gt;   &amp;   ^   |</pre>If <em>expr<sub>1</sub></em> and <em>expr<sub>2</sub></em> are expressions, then<pre>   <em>expr<sub>1</sub> op= expr<sub>2</sub></em></pre>is equivalent to<pre>   <em>expr<sub>1</sub></em> = (<em>expr<sub>1</sub></em>) <em>op</em> (<em>expr<sub>2</sub></em>)</pre>except that <em>expr<sub>1</sub></em> is computed only once. Notice theparentheses around <em>expr<sub>2</sub></em>:<pre>   x *= y + 1</pre>means<pre>   x = x * (y + 1)</pre>rather than<pre>   x = x * y + 1</pre>As an example, the function <tt>bitcount</tt> counts the number of 1-bits in itsinteger argument.<pre>   /* bitcount:  count 1 bits in x */   int bitcount(unsigned x)   {       int b;       for (b = 0; x != 0; x &gt;&gt;= 1)           if (x & 01)               b++;       return b;   }</pre>Declaring the argument <tt>x</tt> to be an <tt>unsigned</tt> ensures that when itis right-shifted, vacated bits will be filled with zeros, not sign bits,regardless of the machine the program is run on.<p>Quite apart from conciseness, assignment operators have the advantage thatthey correspond better to the way people think. We say ``add 2 to <tt>i</tt>''or ``increment <tt>i</tt> by 2'', not ``take <tt>i</tt>, add 2, then put the resultback in <tt>i</tt>''. Thus the expression <tt>i += 2</tt> is preferable to<tt>i = i+2</tt>. In addition, for a complicated expression like<pre>   yyval[yypv[p3+p4] + yypv[p1]] += 2</pre>the assignment operator makes the code easier to understand, since the readerdoesn't have to check painstakingly that two long expressions are indeed thesame, or to wonder why they're not. And an assignment operator may even helpa compiler to produce efficient code.<p>We have already seen that the assignment statement has a value and can occurin expressions; the most common example is<pre>   while ((c = getchar()) != EOF)       ...</pre>The other assignment operators (<tt>+=</tt>, <tt>-=</tt>, etc.) can  also occur inexpressions, although this is less frequent.<p>In all such expressions, the type of an assignment expression is the type ofits left operand, and the value is the value after the assignment.<p><strong>Exercise 2-9.</strong> In a two's complement number system, <tt>x &= (x-1)</tt>deletes the rightmost 1-bit in <tt>x</tt>. Explain why. Use this observation towrite a faster version of <tt>bitcount</tt>.<h2><a name="s2.11">2.11 Conditional Expressions</a></h2>The statements<pre>   if (a &gt; b)       z = a;   else       z = b;</pre>compute in <tt>z</tt> the maximum of <tt>a</tt> and <tt>b</tt>. The<em>conditional expression</em>, written with the ternary operator``<tt>?:</tt>'', provides an alternate way to write this and similarconstructions. In the expression<pre>   <em>expr<sub>1</sub></em> ? <em>expr<sub>2</sub></em> : <em>expr<sub>3</sub></em></pre>the expression <em>expr<sub>1</sub></em> is evaluated first. If it isnon-zero (true), then the expression <em>expr<sub>2</sub></em> is evaluated,and that is the value of the conditional expression. Otherwise<em>expr<sub>3</sub></em> is evaluated, and that is the value. Only one of<em>expr<sub>2</sub></em> and <em>expr<sub>3</sub></em> is evaluated. Thus toset <tt>z</tt> to the maximum of <tt>a</tt> and <tt>b</tt>,<pre>   z = (a &gt; b) ? a : b;    /* z = max(a, b) */</pre>It should be noted that the conditional expression is indeed an expression,and it can be used wherever any other expression can be. If<em>expr<sub>2</sub></em> and <em>expr<sub>3</sub></em> are of differenttypes, the type of the result is determined by the conversion rules discussedearlier in this chapter. For example, if <tt>f</tt> is a <tt>float</tt> and<tt>n</tt> an <tt>int</tt>, then the expression<pre>   (n &gt; 0) ? f : n</pre>is of type <tt>float</tt> regardless of whether <tt>n</tt> is positive.<p>Parentheses are not necessary around the first expression of a conditionalexpression, since the precedence of <tt>?:</tt> is very low, just aboveassignment. They are advisable anyway, however, since they make the conditionpart of the expression easier to see.<p>The conditional expression often leads to succinct code. For example, thisloop prints <tt>n</tt> elements of an array, 10 per line, with each columnseparated by one blank, and with each line (including the last) terminated bya newline.<pre>   for (i = 0; i &lt; n; i++)       printf("%6d%c", a[i], (i%10==9 || i==n-1) ? '\n' : ' ');</pre>A newline is printed after every tenth element, and after the <tt>n</tt>-th.All other elements are followed by one blank. This might look tricky, but it'smore compact than the equivalent <tt>if-else</tt>. Another good example is<pre>   printf("You have %d items%s.\n", n, n==1 ? "" : "s");</pre><strong>Exercise 2-10.</strong> Rewrite the function <tt>lower</tt>, whichconverts upper case letters to lower case, with a conditional expressioninstead of <tt>if-else</tt>.<h2><a name="s2.12">2.12 Precedence and Order of Evaluation</a></h2>Table 2.1  summarizes the rules for precedence and associativity of alloperators, including those that we have not yet discussed. Operators on thesame line have the same precedence; rows are in order of decreasingprecedence, so, for example, <tt>*</tt>, <tt>/</tt>, and <tt>%</tt> all havethe same precedence, which is higher than that of binary <tt>+</tt> and<tt>-</tt>. The ``operator'' <tt>()</tt> refers to function call. Theoperators <tt>-&gt;</tt> and <tt>.</tt> are used to access members ofstructures; they will be covered in <a href="chapter6.html">Chapter 6</a>,along with <tt>sizeof</tt> (size of an object). <ahref="chapter5.html">Chapter 5</a> discusses <tt>*</tt> (indirectionthrough a pointer) and <tt>&</tt> (address of an object), and<a href="chapter3.html">Chapter 3</a> discusses the comma operator.<p><table align="center" border=1><th align="center">Operators <th align="center">Associativity<tr><td><tt>()  []  -&gt;  .</tt></td><td>&nbsp;left to right</td><tr><td><tt>!   ~  ++  --  +  -  *</tt>  (<em>type</em>)  <tt>sizeof</tt></td><td>&nbsp;right to left</td><tr><td><tt>*   /   % </tt></td><td>&nbsp;left to right</td><tr><td><tt>+   -     </tt></td><td>&nbsp;left to right</td><tr><td><tt>&lt;&lt;&nbsp;&nbsp;&gt;&gt;  </tt></td><td>&nbsp;left to right</td><tr><td><tt>&lt;   &lt;=   &gt;   &gt;= </tt></td><td>&nbsp;left to right</td><tr><td><tt>==   !=   </tt></td><td>&nbsp;left to right</td><tr><td><tt>&amp;     </tt></td><td>&nbsp;left to right</td><tr><td><tt>^         </tt></td><td>&nbsp;left to right</td><tr><td><tt>|         </tt></td><td>&nbsp;left to right</td><tr><td><tt>&amp;&amp;</tt></td><td>&nbsp;left to right</td><tr><td><tt>||        </tt></td><td>&nbsp;left to right</td><tr><td><tt>?:        </tt></td><td>&nbsp;right to left</td><tr><td><tt>= += -= *= /= %= &= ^= |= &lt;&lt;= &gt;&gt;=</tt></td><td>&nbsp;right to left</td><tr><td><tt>,         </tt></td><td>&nbsp;left to right</td></table><p>Unary &amp; +, -, and * have higher precedence than the binary forms.<p align="center"><em><strong>Table 2.1:</strong> Precedence and Associativity of Operators</em><p>Note that the precedence of the bitwise operators <tt>&amp;</tt>, <tt>^</tt>,and <tt>|</tt> falls below <tt>==</tt> and <tt>!=</tt>. This implies thatbit-testing expressions like<pre>   if ((x & MASK) == 0) ...</pre>must be fully parenthesized to give proper results.<p>C, like most languages, does not specify the order in which the operands ofan operator are evaluated. (The exceptions are <tt>&amp;&amp;</tt>,<tt>||</tt>, <tt>?:</tt>, and `<tt>,</tt>'.) For example, in a statement like<pre>   x = f() + g();</pre><tt>f</tt> may be evaluated before <tt>g</tt> or vice versa; thus if either<tt>f</tt> or <tt>g</tt> alters a variable on which the other depends,<tt>x</tt> can depend on the order of evaluation. Intermediate results canbe stored in temporary variables to ensure a particular sequence.<p>Similarly, the order in which function arguments are evaluated is notspecified, so the statement<pre>   printf("%d %d\n", ++n, power(2, n));   /* WRONG */</pre>can produce different results with different compilers, depending on whether<tt>n</tt> is incremented before <tt>power</tt> is called. The solution, ofcourse, is to write<pre>   ++n;   printf("%d %d\n", n, power(2, n));</pre>Function calls, nested assignment statements, and increment and decrementoperators cause ``side effects'' - some variable is changed as a by-productof the evaluation of an expression. In any expression involving side effects,there can be subtle dependencies on the order in which variables taking partin the expression are updated. One unhappy situation is typified by thestatement<pre>   a[i] = i++;</pre>The question is whether the subscript is the old value of <tt>i</tt> or thenew. Compilers can interpret this in different ways, and generate differentanswers depending on their interpretation. The standard intentionally leavesmost such matters unspecified. When side effects (assignment to variables)take place within an expression is left to the discretion of the compiler,since the best order depends strongly on machine architecture. (The standarddoes specify that all side effects on arguments take effect before a functionis called, but that would not help in the call to <tt>printf</tt> above.)<p>The moral is that writing code that depends on order of evaluation is a badprogramming practice in any language. Naturally, it is necessary to know whatthings to avoid, but if you don't know <em>how</em> they are done on variousmachines, you won't be tempted to take advantage of a particularimplementation.<p><hr><p align="center"><a href="chapter1.html">Back to Chapter 1</a>&nbsp;--&nbsp;<a href="kandr.html">Index</a>&nbsp;--&nbsp;<a href="chapter3.html">Chapter 3</a><p><hr></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -