📄 faqcat7d4b.html
字号:
comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/constptrconst.html"><!-- qtag -->Question 11.9</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>What's the difference between<TT>const char *p</TT>,<TT>char const *p</TT>,and <TT>char * const p</TT>?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The first twoare interchangeable;theydeclarea pointer to a constant character(you can't changeany pointed-to characters).<TT>char * const p</TT>declares a constant pointer to a(variable)character(i.e. you can't change the pointer).</p><p>Read thesedeclarations``inside out'' to understand them;seequestion<a href="faqcatd3c2.html?sec=decl#cdecl1">1.21</a>.</p><p>References:ISO Sec. 6.5.4.1<br>Rationale Sec. 3.5.4.1<br>H&S Sec. 4.4.4 p. 81<hr><hr><hr><a name="constmismatch"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/constmismatch.html"><!-- qtag -->Question 11.10</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why can't I pass a <TT>char **</TT> to a function which expects a<TT>const char **</TT>?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>You can use a pointer-to-T (for any type T) where apointer-to-const-T is expected.However,therule(an explicit exception)which permits slight mismatchesin qualified pointertypesis not applied recursively,but only at the top level.(<TT>const char **</TT> ispointer-to-pointer-to-const-char,and the exceptiontherefore does not apply.)</p><p>The reason that you cannot assign a<TT>char **</TT> value to a <TT>const char **</TT>pointer is somewhat obscure.Given that the <TT>const</TT> qualifier exists at all,the compiler would like to help you keep your promises not to modify <TT>const</TT> values.That's why you can assigna <TT>char *</TT> to a <TT>const char *</TT>,but not the other way around:it's clearly safe to ``add'' <TT>const</TT>-ness to a simple pointer,but it would be dangerous to take it away.However, suppose you performed the followingmore complicatedseries ofassignments:<pre> const char c = 'x'; /* 1 */ char *p1; /* 2 */ const char **p2 = &p1; /* 3 */ *p2 = &c; /* 4 */ *p1 = 'X'; /* 5 */</pre>In line 3,we assign a <TT>char **</TT> to a <TT>const char **</TT>.(The compiler should complain.)In line 4,we assign a <TT>const char *</TT> to a <TT>const char *</TT>;this is clearly legal.In line 5,we modify what a <TT>char *</TT> points to--this is supposed to be legal.However, <TT>p1</TT> ends up pointing to <TT>c</TT>,which is <TT>const</TT>.This came about in line 4,because <TT>*p2</TT> was really <TT>p1</TT>.This was set up in line 3,which is an assignment of a form that is disallowed,and this is exactly <em>why</em> line 3 is disallowed.</p><p>Assigning a <TT>char **</TT> to a <TT>const char **</TT>(as in line 3, and in the original question)is not immediately dangerous.But it sets up a situation in which <TT>p2</TT>'s promise--thatthe ultimately-pointed-to value won't be modified--cannotbe kept.</p><p>(C++has more complicated rulesfor assigning <TT>const</TT>-qualified pointerswhich let you make more kinds of assignmentswithout incurring warnings,but still protect against inadvertent attemptsto modify <TT>const</TT> values.C++ would still not allowassigning a <TT>char **</TT> to a <TT>const char **</TT>,but it would let you get away withassigning a <TT>char **</TT>to a <TT>const char * const *</TT>.)</p><p>In C,ifyou mustassign or passpointers which have qualifier mismatches atother than the first level of indirection,youmust use explicit casts(e.g. <TT>(const char **)</TT> in this case),although as always,the need for such a cast may indicate a deeper problemwhich the cast doesn't really fix.</p><p>References:ISO Sec. 6.1.2.6, Sec. 6.3.16.1, Sec. 6.5.3<br>H&S Sec. 7.9.1 pp. 221-2<hr><hr><hr><a name="typedefconst"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/typedefconst.html"><!-- qtag -->Question 11.11</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I've gotthe declarations<pre> typedef char *charp; const charp p;</pre>Why is <TT>p</TT> turning out <TT>const</TT>,instead of the characters pointed to?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font><TT>typedef</TT> substitutions are not purely textual.(This is one of the advantages of <TT>typedef</TT>s;see question <a href="faqcatd3c2.html?sec=decl#typedefvsdefine">1.13</a>.)In the declaration<pre> const charp p;</pre><TT>p</TT> is <TT>const</TT>for the same reason that <TT>const int i</TT>declares <TT>i</TT> as <TT>const</TT>.The <TT>typedef</TT>'ed declaration of <TT>p</TT>does not ``look inside'' the <TT>typedef</TT> to see thatthere is a pointer involved.</p><p>Additional links:<a href="faqcat7d4b.html?sec=ansi#typedefconst2">further reading</a></p><p>References:H&S Sec. 4.4.4 pp. 81-2<hr><hr><hr><a name="constvsdefine2"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/constvsdefine2.html"><!-- qtag -->Question 11.11b</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>See question <a href="faqcat204f.html?sec=cpp#constvsdefine">10.5b</a>.<hr><hr><hr><a name="maindecl"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/maindecl.html"><!-- qtag -->Question 11.12a</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>What's the correct declaration of <TT>main()</TT>?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>There aretwo valid declarations:<pre> int main(void) int main(int argc, char **argv)</pre>although theycanbe written in a variety of ways.The second parameter may be declared <TT>char *argv[]</TT>(seequestion <a href="faqcatca65.html?sec=aryptr#aryptrparam">6.4</a>),you can use any names for the two parameters,andyou can useold-style syntax:<pre> int main() int main(argc, argv) int argc; char **argv;</pre></p><p>See also questions <a href="faqcat7d4b.html?sec=ansi#voidmain">11.12b</a>to<a href="faqcat7d4b.html?sec=ansi#voidmainbooks">11.15</a>.</p><p>References:ISO Sec. 5.1.2.2.1, Sec. G.5.1<br>H&S Sec. 20.1 p. 416<br>CT&P Sec. 3.10 pp. 50-51<hr><hr><hr><a name="voidmain"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/voidmain.html"><!-- qtag -->Question 11.12b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Can I declare <TT>main</TT> as <TT>void</TT>,to shut off these annoying``main returns no value'' messages?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>No.<TT>main</TT> must be declared as returning an <TT>int</TT>,and astaking either zero or two arguments,of the appropriate types.If you're calling <TT>exit()</TT> but still getting warnings,you may have to insert a redundant <TT>return</TT> statement(or use some kindof ``not reached'' directive,if available).</p><p>Declaring a function as <TT>void</TT> does not merelyshut off or rearrangewarnings:it may also result in a differentfunction call/return sequence,incompatible with what the caller(in <TT>main</TT>'s case, the C run-time startup code)expects.That is,if the calling sequences for <TT>void</TT>-and <TT>int</TT>-valued functions differ,the startup code is going to be calling <TT>main</TT>usingspecifically the<TT>int</TT>-valued conventions,and if <TT>main</TT> has been improperly declared as <TT>void</TT>,it may notwork.(See also question <a href="faqcat6b6b.html?sec=struct#retcrash">2.18</a>.)</p><p>(Note thatthis discussion of <TT>main</TT>pertains only to ``hosted'' implementations;none of it applies to ``freestanding'' implementations,which may not even have <TT>main</TT>.However,freestanding implementations are comparatively rare,and if you're using one,you probably know it.If you've never heard of the distinction,you're probably using a hosted implementation,and the above rules apply.)</p><p>Additional links:<a href="../../ansi/sd11.html" rel=subdocument>further reading</a></p><p>References:ISO Sec. 5.1.2.2.1, Sec. G.5.1<br>H&S Sec. 20.1 p. 416<br>CT&P Sec. 3.10 pp. 50-51<hr><hr><hr><a name="envp"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/envp.html"><!-- qtag -->Question 11.13</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>But what about <TT>main</TT>'s third argument,<TT>envp</TT>?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>It's a non-standard(though common)extension.If you really need to access the environmentin ways beyond what the standard<TT>getenv</TT> function provides,though,the global variable <TT>environ</TT> is probablya better avenue(though it's equally non-standard).</p><p>References:ISO Sec. G.5.1<br>H&S Sec. 20.1 pp. 416-7<hr><hr><hr><a name="voidmain3"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/voidmain3.html"><!-- qtag -->Question 11.14a</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I believe that declaring <TT>void main()</TT> can't fail,since I'm calling <TT>exit</TT> instead of returning,and anyway my operating system ignores a program's exit/return status.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>It doesn't matter whether <TT>main</TT> returns or not,or whether anyone looks at the status;the problem is thatwhen <TT>main</TT> is misdeclared,its caller(the runtime startup code)may not even be able to <em>call</em> it correctly(due to the potential clash of calling conventions;see question <a href="faqcat7d4b.html?sec=ansi#voidmain">11.12b</a>).</p><p>Youroperating system may ignore the exit status,and <TT>void main()</TT> may work for you,but it is not portable and not correct.</p><p>Additional links:<a href="../../ansi/sd11.html" rel=subdocument>further reading</a><hr><hr><hr><a name="voidmainexamp"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/voidmainexamp.html"><!-- qtag -->Question 11.14b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>So what could go wrong?Are therereally anysystems where <TT>void main()</TT> doesn't work?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>It has been reported thatprograms using <TT>void main()</TT>and compiled using BC++ 4.5can crash.Some compilers(includingDEC C V4.1and <TT>gcc</TT> with certain warnings enabled)will complain about <TT>void main()</TT>.</p><p>Additional links:<a href="http://www.eskimo.com/~scs/readings/voidmain.960823.html">further reading</a><a href="../../ansi/sd12.html" rel=subdocument>examples</a><hr><hr><hr><a name="voidmainbooks"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/voidmainbooks.html"><!-- qtag -->Question 11.15</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>The book I've been using,<I>C Programingfor the Compleat Idiot</I>,always uses <TT>void main()</TT>.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Perhaps its authorcounts himself among the target audience.Many books unaccountably use <TT>void main()</TT> in examples,and assert that it's correct.They'rewrong,or they're assuming that everyone writes codefor systems where it happens to work.<hr><hr><hr><a name="exitvsreturn"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/exitvsreturn.html"><!-- qtag -->Question 11.16</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Is <TT>exit(status)</TT> truly equivalentto returning the same <TT>status</TT> from <TT>main</TT>?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Yes and no.The Standard says thata return from the initial call to <TT>main</TT>is equivalent to calling <TT>exit</TT>.However,a <TT>return</TT> from <TT>main</TT>cannot be expected to workifdata local to <TT>main</TT> might be neededduring cleanup;see also question <a href="faqcat5e04.html?sec=strangeprob#crashatexit">16.4</a>.A fewvery old,nonconforming systemsmayonce have hadproblemswith one or the other form.(Finally, thetwo forms are obviously not equivalentin a recursive call to <TT>main</TT>.)</p><p>References:K&R2 Sec. 7.6 pp. 163-4<br>ISO Sec. 5.1.2.2.3<hr><hr><hr><a name="stringize"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ansi/stringize.html"><!-- qtag -->Question 11.17</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I'm trying to usethe ANSI ``stringizing'' preprocessing operator`<TT>#</TT>'to insert the value of a symbolic constant into a message,but it keepsstringizing the macro's name rather than itsvalue.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>It turns out thatthe definition of <TT>#</TT>says thatit's supposed to stringizea macro argument immediately,without further expanding it(if the argument happens to bethe name ofanother macro).You can usesomething like the followingtwo-stepprocedureto force a macro to be expanded as well asstringized:<pre>#define Str(x) #x#define Xstr(x) Str(x)#define OP pluschar *opname = Xstr(OP);</pre>Thiscodesets <TT>opname</TT> to <TT>"plus"</TT> rather than <TT>"OP"</TT>.(It works becausethe <TT>Xstr()</TT> macro expands its argument,and then <TT>Str()</TT> stringizes it.)<a href="../../ansi/fn50.html" rel=subdocument>[footnote]</a></p><p>An equivalent circumlocution is necessarywith thetoken-pastingoperator <TT>##</TT>when the values(rather than the names)of two macros are to be concatenated.</p><p>Note that both <TT>#</TT> and <TT>##</TT> operate
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -