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

📄 faqcat204f.html

📁 this is a mirrored site c-faq. thought might need offline
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN"><!-- This collection of hypertext pages is Copyright 1995-2005 by Steve Summit. --><!-- Content from the book "C Programming FAQs: Frequently Asked Questions" --><!-- (Addison-Wesley, 1995, ISBN 0-201-84519-9) is made available here by --><!-- permission of the author and the publisher as a service to the community. --><!-- It is intended to complement the use of the published text --><!-- and is protected by international copyright laws. --><!-- The on-line content may be accessed freely for personal use --><!-- but may not be published or retransmitted without explicit permission. --><!-- --><!-- this page built Sat Dec 24 21:47:46 2005 by faqproc version 2.7 --><!-- from source file cpp.sgml dated Wed Dec 21 13:52:14 2005 --><!-- corresponding to FAQ list version 4.0 --><html><!-- Mirrored from c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=cpp by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 07:57:58 GMT --><head><base ><meta name=GENERATOR content="faqproc"><title>C Preprocessor</title></head><body bgcolor="#ffffff"><H1>10. C Preprocessor</H1><a name="safemacros"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../cpp/safemacros.html"><!-- qtag -->Question 10.1</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I'm trying to definea few simple little function-like macrossuch as<pre>	#define square(x) x * x</pre>but they're not always working.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>There are three important rules to remember when definingfunction-like macros:<OL><li>The macro expansion must always be parenthesizedto protectany lower-precedence operatorsfrom the surrounding expression.Given the(incorrect)<TT>square()</TT> macro above,the invocation<pre>	1 / square(n)</pre>would expand to<pre>	1 / n * n</pre>(which evaluates as <TT>(1 / n) * n</TT>),whilewhat you want is<pre>	1 / (n * n)</pre>(In this case, the problem is one of associativity rather than precedence, but the effect is the same.)<li>Within the macro definition,alloccurrencesof the parametersmust be parenthesizedto protectany low-precedence operatorsin the actual argumentsfrom therest of the macro expansion.Againgiven the <TT>square()</TT> macro above,the invocation<pre>	square(n + 1)</pre>would expand to<pre>	n + 1 * n + 1</pre>But what you want is<pre>	(n + 1) * (n + 1)</pre><li>If a parameter appears several timesin the expansion,the macro may not work properlyif the actual argumentis an expression withside effects.Yet againgiven the <TT>square()</TT> macro above,the invocation<pre>	square(i++)</pre>would expand to<pre>	i++ * i++</pre>which is undefined(see question <a href="faqcatee08.html?sec=expr#evalorder2">3.2</a>).</OL></p><p>The proper definition of a <TT>square</TT> macro,to comply with rules 1 and 2 above,is<pre>	#define square(x) ((x) * (x))</pre>Complying with rule 3 is harder.Sometimes,careful exploitation of the short-circuiting behavior ofthe<TT>&amp;&amp;</TT>, <TT>||</TT>, or <TT>?:</TT>operators(see question <a href="faqcatee08.html?sec=expr#shortcircuit">3.6</a>)can arrange that a parameter which appears several timesis guaranteed to be evaluated exactly once.Sometimes, the macro isjustdocumented as being unsafe,and callers must remembernot to use it on arguments with side effects.Other times,it may be advisable <em>not</em> tocompose a function-like macroif it can't be made safe.</p><p>(As a stylistic convention,macros are often defined with capitalized or all-upper-case names,to make it obvious that they are macros.It may be acceptable to define a function-like macrowith an all-lower-case name,if it truly simulates a function,but only if it complies with all three rules above.Since the squaring macro we've been discussing does not,it should be defined as something like<pre>	#define Square(x) ((x) * (x))	/* UNSAFE */</pre>if it is to be used at all.)</p><p>References:K&amp;R1 Sec. 4.11 p. 87<br>K&amp;R2 Sec. 4.11.2 p. 90<br>H&amp;S Secs. 3.3.6,3.3.7 pp. 49-50<br>CT&amp;P Sec. 6.2 pp. 78-80<hr><hr><hr><a name="slm"><hr><hr><hr><a name="swapmacro"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../cpp/swapmacro.html"><!-- qtag -->Question 10.3</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I write a generic macro to swap two values?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>There is no good answer to this question.If the values are integers, a well-known trick using exclusive-ORcould perhapsbe used,but it will not work for floating-point values orpointers,or if the two values are the same variable.(See questions <a href="faqcatee08.html?sec=expr#xorswapexpr">3.3b</a> and <a href="faqcat38c2.html?sec=misc#swapnotemp">20.15c</a>.)If the macro is intended to beused on values of arbitrary type(the usual goal),any solution involving a temporary variable is problematical,because:<UL><li>It's hard to givethe temporarya name that won't clash with anything.(Any name you pickmight be the actual name of one of the variables being swapped.If you triedusing <TT>##</TT>to concatenate the names of the two actual arguments,to ensure that it won't match either one,it might still not be uniqueif the concatenated name is longer than 31 characters,<a href="../../cpp/identl.html" rel=subdocument>[footnote]</a>and itwouldn't let you swap things like <TT>a[i]</TT> that aren't simple identifiers.You could probably get away with using a name like <TT>_tmp</TT> in the ``no man's land'' between the user and implementation namespaces; see question <a href="faqcatd3c2.html?sec=decl#namespace">1.29</a>.)<li>Either it can't be declared with the right type(because standard C does not provide a <TT>typeof</TT> operator),or(if it copies objects byte-by-byte,perhaps with <TT>memcpy</TT>,to a temporary array sized with <TT>sizeof</TT>)the macro can't be used on operands which are declared <TT>register</TT>.</UL></p><p>The best all-around solution is probably to forget about using amacro,unless you're willing to pass in the type as a third argument.(Also,if you're trying to swap entire structures or arrays,you probably want toexchange pointersinstead.)If you're worried about the use of an ugly temporary, and knowthat your machine provides an efficient exchange instruction, convince yourcompiler vendor to recognize the standard three-assignment swapidiom in the optimization phase.</p><p>If you're consumed by a passionate desireto solve this problem once and for all,please reconsider;there are better problems worthier of your energies.</p><p>Additional links:<a href="../../cpp/sd6.html" rel=subdocument>so you think you have a solution</a><hr><hr><hr><a name="multistmt"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../cpp/multistmt.html"><!-- qtag -->Question 10.4</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>What's the best way to write a multi-statement macro?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The usual goal is tobe able toinvoke the macro as if it werean expression statement consisting of a function call:<pre>	MACRO(arg1, arg2);</pre>This means that the ``caller'' will be supplying the final semicolon,so the macro body should not.The macro body cannot thereforebe a simplebrace-enclosedcompound statement,becauseof thepossibilitythat the macro could be usedas the if branch of an if/else statement with an explicit elseclause:<pre>	if(cond)		MACRO(arg1, arg2);	else	/* some other code */</pre>Ifthe macroexpandedtoa simplecompound statement,the final,caller-suppliedsemicolonwould be a syntax error:<pre>	if(cond)		{stmt1; stmt2;};	else	/* some other code */</pre></p><p>The traditional solution,therefore, is to use<pre>	#define MACRO(arg1, arg2) do {	\		/* declarations */	\		stmt1;			\		stmt2;			\		/* ... */		\		} while(0)	/* (no trailing ; ) */</pre>When the caller appends a semicolon, this expansionbecomes a single statement regardless of context.(An optimizing compiler will remove any ``dead'' tests orbranches on the constant condition 0, although <TT>lint</TT> may complain.)</p><p>(Another possibility might be<pre>	#define MACRO(arg1, arg2) if(1) { \		stmt1; \		stmt2; \		} else</pre>but itis inferior,sinceit quietlybreaks the surrounding codeifthe caller happens to forget to appendthe semicolon upon invocation.)</p><p>If all of the statements in the intended macro are simple expressions,with no declarationsor loops,another technique is towrite a single, parenthesized expressionusing one or more comma operators:<pre>	#define FUNC(arg1, arg2) (expr1, expr2, expr3)</pre>(For anexample,see thefirst <TT>DEBUG()</TT>macro in question<a href="faqcat204f.html?sec=cpp#varargs">10.26</a>.)This technique also allows a value(in this case,<TT>expr3</TT>)to be ``returned.''</p><p>Some compilers,e.g. <TT>gcc</TT>,are also able to expand compact functions in-line,either automatically or at the programmer's request(perhaps with a nonstandard``<TT>inline</TT>'' keywordor other extension).</p><p>References:H&amp;S Sec. 3.3.2 p. 45<br>CT&amp;P Sec. 6.3 pp. 82-3<hr><hr><hr><a name="typedefvsdefine"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../cpp/typedefvsdefine.html"><!-- qtag -->Question 10.5</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>What's the difference between using a <TT>typedef</TT>ora <TT>#define</TT>for a user-defined type?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>See question <a href="faqcatd3c2.html?sec=decl#typedefvsdefine">1.13</a>.<hr><hr><hr><a name="constvsdefine"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../cpp/constvsdefine.html"><!-- qtag -->Question 10.5b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>What's the difference between<pre>	const MAXSIZE = 100;</pre><pre>and</pre><pre>	#define MAXSIZE 100</pre></p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>A preprocessor<TT>#define</TT> gives you a true compile-time constant.In C, <TT>const</TT>gives you a run-time object which you're not supposed to try to modify;``<TT>const</TT>'' really means ``<TT>readonly</TT>''.See also the question <a href="faqcat7d4b.html?sec=ansi#constasconst">11.8</a>.(But in C++, <TT>const</TT> is closer to <TT>#define</TT>.)</p><p>Additional links:<a href="faqcat204f.html?sec=cpp#constdefine2">longer explanation</a><hr><hr><hr><a name="hfiles"><h1>comp.lang.c FAQ list<font color=blue>&middot;</font><a href="../../cpp/hfiles.html"><!-- qtag -->Question 10.6</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I'm splitting up a programinto multiple source filesfor the first time,and I'm wondering what to put in <TT>.c</TT> filesand what to put in <TT>.h</TT> files.(What does ``<TT>.h</TT>''mean,anyway?)</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>As a general rule, you should put these things in header(<TT>.h</TT>) files:<blockquote><pre>macro definitions (preprocessor <TT>#define</TT>s)structure, union, and enumeration declarationstypedef declarationsexternal function declarations (see also question <a href="faqcatd3c2.html?sec=decl#extern">1.11</a>)global variable declarations</pre></blockquote></p><p>It's especially important to put a declaration or definition in a header file when it will be shared between several other files.Don't repeat a declaration or macro definition at the top of two or more source files;do put it in a header file and <TT>#include</TT> it wherever needed.The reason is not just to save typing:you want to set things up so that whenever a declaration or definition changes,you only have to change it in one place,with the update propagated toall source filesconsistently.(In particular, never put external functionprototypes in <TT>.c</TT> files.See also question <a href="faqcatd3c2.html?sec=decl#decldef">1.7</a>.)</p><p>On the other hand,when a definition or declaration should remain private to one<TT>.c</TT>file, it'sfineto

⌨️ 快捷键说明

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