📄 faqcat38c2.html
字号:
because shifting is more efficient.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>This is an excellent example of a potentially riskyand usually unnecessary optimization.Any compiler worthy of the name can replace aconstant, power-of-twomultiplication with a left shift,or asimilardivision of an unsigned quantity with a right shift.(Ritchie's original PDP-11 compiler,though it ran in less than 64K of memoryand omitted several features now considered mandatory,performed both of these optimizations,without eventurning on its optional optimization pass.)Furthermore,a compiler will make these optimizations only when they're correct;many programmers overlook the factthat shifting a negative valueto therightis <em>not</em> equivalent to division.(Therefore,when you need to make sure that these optimizations are performed,you may have to declare relevant variables as <TT>unsigned</TT>.)<hr><hr><hr><a name="unsshift"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../misc/unsshift.html"><!-- qtag -->Question 20.15b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>People claim that optimizing compilers are goodand that we no longer have to write things in assembler for speed,butmy compilercan't evenreplace <TT>i/=2</TT> with a shift.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Was <TT>i</TT> signed or unsigned?If it was signed,a shift is not equivalent(hint: think about the result if <TT>i</TT> is negative and odd),so the compiler was correct not to use it.<hr><hr><hr><a name="swapnotemp"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../misc/swapnotemp.html"><!-- qtag -->Question 20.15c</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I swap two values without using a temporary?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Thestandard hoary old assembly language programmer'strick is:<pre>a ^= b;b ^= a;a ^= b;</pre>But this sort of code has little place in modern,HLL programming.Temporary variables are essentially free,and the idiomatic code using three assignments,namely<pre> int t = a; a = b; b = t;</pre>is not only clearer to the human reader,it is more likely to be recognized by the compilerand turned into the most-efficient code(e.g. perhaps even using an EXCH instruction).The latter code is obviously also amenableto use with pointers and floating-point values,unlike the XOR trick.Seealso questions<a href="faqcatee08.html?sec=expr#xorswapexpr">3.3b</a> and <a href="faqcat204f.html?sec=cpp#swapmacro">10.3</a>.</p><p>Additional links:<a href="../../misc/swap.homework.html">further reading</a><hr><hr><hr><a name="switchimpl"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../misc/switchimpl.html"><!-- qtag -->Question 20.16</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Which is more efficient,a <TT>switch</TT> statement or an <TT>if</TT>/<TT>else</TT> chain?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The differences,if any,are likely to be slight.The <TT>switch</TT> statement was designed to be efficiently implementable,though the compiler maychoose touse the equivalent of an if/else chain(as opposed to acompactjump table)if the case labels are sparsely distributed.</p><p>Do use <TT>switch</TT> when you can:it's certainly cleaner,and perhaps more efficient(and certainlyshould never beany <em>less</em> efficient).</p><p>See also questions <a href="faqcat38c2.html?sec=misc#strswitch">20.17</a>and <a href="faqcat38c2.html?sec=misc#nonconstcase">20.18</a>.<hr><hr><hr><a name="strswitch"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../misc/strswitch.html"><!-- qtag -->Question 20.17</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Is there a way to <TT>switch</TT> on strings?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Not directly.Sometimes, it's appropriateto use a separate function to map strings to integer codes,and then switch on those:<pre>#define CODE_APPLE 1#define CODE_ORANGE 2#define CODE_NONE 0switch(classifyfunc(string)) { case CODE_APPLE: ... case CODE_ORANGE: ... case CODE_NONE: ...}</pre>where <TT>classifyfunc</TT> looks something like<pre>static struct lookuptab { char *string; int code;} tab[] = { {"apple", CODE_APPLE}, {"orange", CODE_ORANGE},};classifyfunc(char *string){ int i; for(i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) if(strcmp(tab[i].string, string) == 0) return tab[i].code; return CODE_NONE;}</pre></p><p>Otherwise, of course,you can fall back ona conventional <TT>if</TT>/<TT>else</TT> chain:<pre> if(strcmp(string, "apple") == 0) { ... } else if(strcmp(string, "orange") == 0) { ... }</pre>(A macro like<TT>Streq()</TT>from question <a href="faqcataae2.html?sec=style#strcmp">17.3</a>can make these comparisons a bit more convenient.)</p><p>See alsoquestions <a href="faqcat204f.html?sec=cpp#ifstrcmp">10.12</a>, <a href="faqcat38c2.html?sec=misc#switchimpl">20.16</a>, <a href="faqcat38c2.html?sec=misc#nonconstcase">20.18</a>, and <a href="faqcat38c2.html?sec=misc#hash">20.29</a>.</p><p>References:K&R1 Sec. 3.4 p. 55<br>K&R2 Sec. 3.4 p. 58<br>ISO Sec. 6.6.4.2<br>H&S Sec. 8.7 p. 248<hr><hr><hr><a name="nonconstcase"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../misc/nonconstcase.html"><!-- qtag -->Question 20.18</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Is there a way to have non-constant <TT>case</TT> labels(i.e. ranges or arbitrary expressions)?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>No.The <TT>switch</TT> statementwas originally designed to be quite simple for the compiler to translate,therefore case labels are limited to single, constant, integral expressions.You <em>can</em> attach several case labels to the same statement,which will let you cover a small range if you don't mind listing all cases explicitly.</p><p>If you want to select on arbitrary rangesor non-constant expressions,you'll have to use an <TT>if</TT>/<TT>else</TT> chain.</p><p>See alsoquestions <a href="faqcat38c2.html?sec=misc#switchimpl">20.16</a> and <a href="faqcat38c2.html?sec=misc#strswitch">20.17</a>.</p><p>References:K&R1 Sec. 3.4 p. 55<br>K&R2 Sec. 3.4 p. 58<br>ISO Sec. 6.6.4.2<br>Rationale Sec. 3.6.4.2<br>H&S Sec. 8.7 p. 248<hr><hr><hr><a name="returnparens"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../misc/returnparens.html"><!-- qtag -->Question 20.19</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Are the outer parenthesesin <TT>return</TT> statementsreally optional?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Yes.</p><p>Long ago,in the early days of C,they were required,and just enough people learned C then,and wrote code which is still in circulation,that thenotionthatthey might still be requirediswidespread.</p><p>(As it happens,parentheses are optional with the<TT>sizeof</TT>operator, too,under certain circumstances.)</p><p>References:K&R1 Sec. A18.3 p. 218<br>ISO Sec. 6.3.3, Sec. 6.6.6<br>H&S Sec. 8.9 p. 254<hr><hr><hr><a name="nestcomment"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../misc/nestcomment.html"><!-- qtag -->Question 20.20</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why don't C comments nest?How am I supposed to comment out code containing comments?Arecommentslegal inside quoted strings?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>C comments don't nestmostlybecause PL/I's comments,which C's are borrowed from,don't either.Therefore,it is usually better to ``comment out''large sections of code, which might contain comments, with<TT>#ifdef</TT> or <TT>#if 0</TT>(but see question<a href="faqcat7d4b.html?sec=ansi#ifdefsyntax">11.19</a>).</p><p>The character sequences <TT>/*</TT> and <TT>*/</TT> arenot special within double-quotedstrings,and do not therefore introduce comments,because a program(particularly one which is generating C code as output)might want to print them.(It is hard to imagine why anyone would want or need to place acomment inside a quoted string.It is easy to imagine a program needing to print "<TT>/*</TT>".)</p><p>Note also that <TT>//</TT> commentshave only become legal in C as of C99.</p><p>References:K&R1 Sec. A2.1 p. 179<br>K&R2 Sec. A2.2 p. 192<br>ISO Sec. 6.1.9, Annex F<br>Rationale Sec. 3.1.9<br>H&S Sec. 2.2 pp. 18-9<br>PCS Sec. 10 p. 130<hr><hr><hr><a name="multibreak"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../misc/multibreak.html"><!-- qtag -->Question 20.20b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why isn't there a numbered, multi-level <TT>break</TT> statementto break out of several loops at once?What am I supposed to use instead, a <TT>goto</TT>?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>First, remember why it is that <TT>break</TT> and <TT>continue</TT>exist at all--they are,in effect, ``structured <TT>goto</TT>s''used in preference to <TT>goto</TT>(and accepted as alternatives by most of those who shun <TT>goto</TT>)because they are clean and structured andpretty muchrestricted to a common, idiomatic usages.A hypothetical multi-level <TT>break</TT>, on the other hand,would rapidly lose the inherent cleanliness of the single<TT>break</TT>--programmers and readers of codewould have to carefully count nesting levelsto figure out what a given <TT>break</TT> did,and the insertion of a new intermediately-nested loopcould, er, break things badly.(By this analysis,a numbered <TT>break</TT> statement canbe even more confusing and error-prone than a <TT>goto</TT>/label pair.)</p><p>The right way to break out of several loops at once(which C also does not have)involves a syntax which allows the naming of loops,so that a <TT>break</TT> statement can specifythe name of the loop to be broken out of.</p><p>If you do have to break out of more than one loop at once(or break out of a loop from inside a switch,where <TT>break</TT> would merely end a <TT>case</TT> label)yes, go ahead and use a <TT>goto</TT>.(But when you find the need for a multi-level break,it's often a sign that the loop should be broken out to its own function,at which point you can achieve roughly the same effectas that multi-level breakby using a premature return.)<hr><hr><hr><a name="funkyasgnop"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../misc/funkyasgnop.html"><!-- qtag -->Question 20.21</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>There seem to be a few missing operators, like <TT>^^</TT>, <TT>&&=</TT>, and <TT>->=</TT>.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>A logicalexclusive-or operator(hypothetically ``<TT>^^</TT>'')would be nice,but it couldn't possibly have short-circuitingbehavioranalogous to <TT>&&</TT> and <TT>||</TT>(see question <a href="faqcatee08.html?sec=expr#shortcircuit">3.6</a>).Similarly,it's not clear how short-circuiting would apply tohypothetical assignment operators <TT>&&=</TT> and <TT>||=</TT>.(It's also not clearhow often <TT>&&=</TT> and <TT>||=</TT>would actually be needed.)</p><p>Though <TT>p = p->next</TT> is an extremely common idiom for traversing a linked list,<TT>-></TT> is not a binary arithmetic operator.Ahypothetical<TT>->=</TT> operatortherefore wouldn't really fit the patternof the other assignment operators.</p><p>You can write an exclusive-or macro in several ways:<pre> #define XOR(a, b) ((a) && !(b) || !(a) && (b)) /* 1 */ #define XOR(a, b) (!!(a) ^ !!(b)) /* 2 */ #define XOR(a, b) (!!(a) != !!(b)) /* 3 */ #define XOR(a, b) (!(a) ^ !(b)) /* 4 */ #define XOR(a, b) (!(a) != !(b)) /* 5 */ #define XOR(a, b) ((a) ? !(b) : !!(b)) /* 6 */</pre>The first is straight from the definition,but is poor because it may evaluate its arguments multiple times(see question <a href="faqcat204f.html?sec=cpp#safemacros">10.1</a>).The second and third``normalize''their operands<a href="../../misc/norml.html" rel=subdocument>[footnote]</a>to strict 0/1 by negating them twice--thesecond then applies bitwise exclusive or(to the single remaining bit);the third one implements exclusive-or as <TT>!=</TT>.The fourth and fifth are based on an elementaryidentity in Boolean algebra,namely that<blockquote> _ _<br>a (+) b = a (+) b</blockquote>(where (+) is exclusive-orand an overbar indicates negation).Finally,the sixth one,suggested by Lawrence Kirbyand Dan Pop,uses the <TT>?:</TT> operatorto guarantee a sequence point between the two operands,as for <TT>&&</TT> and <TT>||</TT>.(There is still no ``short circuiting'' behavior,though,nor can there be.)</p><p>Additional links:A<a href="../../misc/xor.dmr.html">definitive answer</a>from Dennis Ritchie about <TT>^^</TT><hr><hr><hr><a name="circshift"><h1>comp.lang.c FAQ list
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -