📄 faqcatee08.html
字号:
<p>References:K&R1 Sec. 2.8 p. 43<br>K&R2 Sec. 2.8 p. 47<br>ISO Sec. 6.3.2.4, Sec. 6.3.3.1<br>H&S Sec. 7.4.4 pp. 192-3, Sec. 7.5.8 pp. 199-200<hr><hr><hr><a name="transitivity"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../expr/transitivity.html"><!-- qtag -->Question 3.13</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I need to check whether one number lies between two others.Why doesn't<pre>if(a < b < c)</pre>work?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The relational operators,such as <TT><</TT>,are all binary;they compare two operands and returna true or false(1 or 0)result.Therefore, the expression<TT>a < b < c</TT> compares <TT>a</TT> to <TT>b</TT>,and then checks whether the resulting 1 or 0 is less than <TT>c</TT>.(To see it more clearly,imagine that it had been written as<TT>(a < b) < c</TT>,because that's how the compiler interprets it.)To check whether one number lies between two others,use code like this:<pre> if(a < b && b < c)</pre></p><p>References:K&R1 Sec. 2.6 p. 38<br>K&R2 Sec. 2.6 pp. 41-2<br>ISO Sec. 6.3.8, Sec. 6.3.9<br>H&S Secs. 7.6.4,7.6.5 pp. 207-210<hr><hr><hr><a name="intoverflow1"><hr><hr><hr><a name="intovf3"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../expr/intovf3.html"><!-- qtag -->Question 3.14b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I ensure that integer arithmetic doesn't overflow?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>See question <a href="faqcat38c2.html?sec=misc#intovf">20.6b</a>.<hr><hr><hr><a name="truncation1"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../expr/truncation1.html"><!-- qtag -->Question 3.15</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why does the code<pre>double degC, degF;degC = 5 / 9 * (degF - 32);</pre>keep giving me 0?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>If both operands of a binary operator are integers,C performs an integer operation,regardless of the type of the rest of the expression.In this case,the integer operation istruncating division,yielding 5 / 9 = 0.(Note,though,that the problem of having subexpressions evaluated in anunexpected typeis not restricted to division,nor for that matter to type <TT>int</TT>.)If you cast one of the operands to <TT>float</TT> or <TT>double</TT>,or use a floating-point constant,i.e.<pre> degC = (double)5 / 9 * (degF - 32);or degC = 5.0 / 9 * (degF - 32);</pre>it willwork as you expect.Note that the cast must be on one of the operands;casting the result(as in <TT>(double)(5 / 9) * (degF - 32)</TT>)would not help.</p><p>See also question <a href="faqcatee08.html?sec=expr#intoverflow1">3.14</a>.</p><p>References:K&R1 Sec. 1.2 p. 10, Sec. 2.7 p. 41<br>K&R2 Sec. 1.2 p. 10, Sec. 2.7 p. 44<br>ISO Sec. 6.2.1.5<br>H&S Sec. 6.3.4 p. 176<hr><hr><hr><a name="qcolonlhs"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../expr/qcolonlhs.html"><!-- qtag -->Question 3.16</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I have a complicated expression whichI haveto assignto one of two variables,depending on a condition.Can I use code like this?<pre> ((condition) ? a : b) = complicated_expression;</pre></p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>No.The <TT>?:</TT> operator,like most operators,yields a value,and you can't assign to a value.(In other words, <TT>?:</TT> does not yield an <a href="../../sx1/index.html#lvalue"><dfn>lvalue</dfn></a>.)If you really want to,you can try something like<pre> *((condition) ? &a : &b) = complicated_expression;</pre>although this is admittedly not as pretty.</p><p>References:ISO Sec. 6.3.15<br>H&S Sec. 7.1 pp. 179-180<hr><hr><hr><a name="ternprec"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../expr/ternprec.html"><!-- qtag -->Question 3.17</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I havesome codecontaining expressionslike<pre>a ? b = c : d</pre>and some compilers are accepting it but some are not.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>In the original definition ofthe language,<TT>=</TT> was of lower precedencethan <TT>?:</TT>,so early compilers tended to trip up on an expression likethe one above,attempting to parse it asif it had been written<pre> (a ? b) = (c : d)</pre>Since it has no other sensible meaning, however,later compilers have allowedthe expression,and interpret itas ifan inner set ofparentheses were implied:<pre> a ? (b = c) : d</pre>Here,the left-hand operand of the <TT>=</TT> is simply <TT>b</TT>,not the invalid <TT>a ? b</TT>.In fact,the grammar specified in the ANSI/ISO C Standardeffectively requires this interpretation.(The grammar in the Standardis not precedence-based,and says that any expression may appear betweenthe <TT>?</TT> and <TT>:</TT> symbols.)</p><p>An expression like the one in the question isperfectly acceptable to an ANSI compiler,but if you ever have to compile it under an older compiler,you can always add the explicit, inner parentheses.</p><p>References:K&R1 Sec. 2.12 p. 49<br>ISO Sec. 6.3.15<br>Rationale Sec. 3.3.15<hr><hr><hr><a name="unswarn"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../expr/unswarn.html"><!-- qtag -->Question 3.18</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>What does the warning``semantics of `<TT>></TT>' change in ANSI C''mean?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>This message represents an attemptby certain(perhaps overzealous)compilersto warn youthatsome codemay perform differently under the ANSI C ``value preserving''rules than under the older ``unsigned preserving'' rules.</p><p>The wording of thismessageis rather confusing because what has changedis not really the semantics of the <TT>></TT> operatoritself(infact,almost any C operator can appear in themessage),butratherthe semanticsof the implicit conversionswhich always occur whentwo dissimilar types meet across a binary operator,or when a narrow integral type must be promoted.</p><p>(If you didn't think you were using any unsigned valuesin your expression,themost likelyculprit is <TT>strlen</TT>.In Standard C,<TT>strlen</TT> returns<TT>size_t</TT>,which is an unsigned type.)</p><p>See question <a href="faqcatee08.html?sec=expr#preservingrules">3.19</a>.<hr><hr><hr><a name="preservingrules"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../expr/preservingrules.html"><!-- qtag -->Question 3.19</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>What's the difference between the ``unsigned preserving''and ``value preserving'' rules?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>These rules concern the behaviorwhenan unsigned type must be promoted to a ``larger'' type.Should it be promoted to a larger signed or unsigned type?(To foreshadow the answer,it may dependon whether the larger type is truly larger.)</p><p>Under the unsigned preserving(also called ``sign preserving'')rules,the promoted typeis always unsigned.This rule has the virtue of simplicity,but itcan lead to surprises(see the first example below).</p><p>Under the value preserving rules,the conversion depends on the actual sizes of theoriginal and promotedtypes.If the promoted type is truly larger--whichmeans that it can represent all the values of theoriginal, unsignedtype as signed values--then the promoted typeis signed.If the two types are actually the same size,then the promoted type is unsigned(as for the unsigned preserving rules).</p><p>Since the <em>actual</em> sizes of the types are usedin making the determination,the resultswill vary from machine to machine.On some machines,<TT>short int</TT> is smaller than <TT>int</TT>,but on some machines, they're the same size.On some machines,<TT>int</TT> is smaller than <TT>long int</TT>,but on some machines, they're the same size.</p><p>In practice, the difference between the unsigned andvalue preserving rules matters most often when one operand ofa binaryoperator is (or promotes to) <TT>int</TT>and the other one might,depending on the promotion rules, be either <TT>int</TT> or<TT>unsigned int</TT>.If one operand is <TT>unsigned int</TT>, the otherwill be converted to that type--almost certainly causingan undesired result if its value was negative(again, see the first example below).When the ANSIC Standard was established, the value preserving rules werechosen, to reduce the number of cases wherethese surprising results occur.(On the other hand,the value preserving rules also reducethe number of <em>predictable</em> cases,because portable programs cannot depend on a machine's type sizesand hence cannot know which way the value preserving rules will fall.)</p><p>Here is a contrived exampleshowing the sort of surprisethat canoccur under the unsigned preserving rules:<pre> unsigned short us = 10; int i = -5; if(i > us) printf("whoops!\n");</pre>The important issue is howthe expression <TT>i > us</TT> is evaluated.Under the unsigned preserving rules(and under the value preserving rules on a machine where <TT>short</TT> integers and plain integers are the same size),<TT>us</TT> is promoted to <TT>unsigned int</TT>.The usual integral conversions say that when types<TT>unsigned int</TT> and <TT>int</TT> meet across a binary operator,both operands are converted to unsigned,so <TT>i</TT> is converted to <TT>unsigned int</TT>, as well.The old value of <TT>i</TT>, -5,is converted to some large unsigned value (65,531 on a 16-bit machine).This converted value is greater than 10,so the code prints ``whoops!''</p><p>Under the value preserving rules,on a machine whereplain integers are larger than <TT>short</TT> integers,<TT>us</TT> is converted to a plain <TT>int</TT>(and retains its value, 10),and <TT>i</TT> remains a plain <TT>int</TT>.Theexpression is not true,and the code prints nothing.(To see why the values can be preserved only when the signed type is larger,remember that a value like 40,000 can be representedas an unsigned 16-bit integer but not as a signed one.)</p><p>Unfortunately, the value preserving rulesdo not prevent all surprises.The example just presented still prints ``whoops''on a machine where short and plain integers are the same size.Thevalue preserving rulesmay also inject a few surprises of theirown--considerthe code:<pre> unsigned char uc = 0x80; unsigned long ul = 0; ul |= uc << 8; printf("0x%lx\n", ul);</pre>Before being left-shifted, <TT>uc</TT> is promoted.Under the unsigned preserving rules,it is promoted to an <TT>unsigned int</TT>,and the code goes on to print <TT>0x8000</TT>,as expected.Under the value preserving rules, however,<TT>uc</TT> is promoted to a <em>signed</em> int(as long as <TT>int</TT>'s are larger than <TT>char</TT>'s,which is usually the case).The intermediate result <TT>uc << 8</TT>goes on tomeet<TT>ul</TT>,which is <TT>unsigned long</TT>.The signed, intermediate result must therefore be promoted as well,and if <TT>int</TT> is smaller than <TT>long</TT>,the intermediate resultis sign-extended,becoming<TT>0xffff8000</TT> on a machine with 32-bit <TT>long</TT>s.On such a machine,the code prints <TT>0xffff8000</TT>,which is probably not what was expected.(On machines where <TT>int</TT> and <TT>long</TT> are the same size,the codeprints <TT>0x8000</TT>under either set of rules.)</p><p>To avoid surprises(under either set of rules,or due to an unexpected change of rules),it's best to avoid mixing signed and unsigned types in the same expression,although as the second example shows,this rule is not always sufficient.You canalwaysuse explicit caststo indicate,unambiguously,exactlywhere and how you want conversions performed;see questions<a href="faqcat1d60.html?sec=stdio#extconform">12.42</a>and<a href="faqcat5e04.html?sec=strangeprob#ptralign">16.7</a>for examples.(Some compilers attempt to warn you when they detect ambiguous casesor expressions which would have behaved differently under the unsigned preserving rules,although sometimes these warnings fire too often;see also question <a href="faqcatee08.html?sec=expr#unswarn">3.18</a>.)</p><p>References:K&R2 Sec. 2.7 p. 44, Sec. A6.5 p. 198, Appendix C p. 260<br>ISO Sec. 6.2.1.1, Sec. 6.2.1.2, Sec. 6.2.1.5<br>Rationale Sec. 3.2.1.1<br>H&S Secs. 6.3.3,6.3.4 pp. 174-177<hr><hr><hr><hr><p>Read sequentially:<a href="faqcat6b6b.html?sec=struct" rev=precedes>prev</a><a href="faqcatabdc.html?sec=ptrs" rel=precedes>next</a><a href="faqcat.html" rev=subdocument>up</a></p><hr><p><br><!-- lastfooter --><a href="../../about.html">about this FAQ list</a> <a href="../../eskimo.html">about eskimo</a> <a href="../../search.html">search</a> <a href="../../feedback.html">feedback</a> <a href="../../expr/copyright.html">copyright</a><p>Hosted by<a href="http://www.eskimo.com/"><img src="../../../www.eskimo.com/img/link/eskitiny.gif" alt="Eskimo North"></a></body><!-- Mirrored from c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=expr by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 07:57:39 GMT --></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -