📄 faqcatd3c2.html
字号:
typedef pfpc fpfpc(); /* function returning... */ typedef fpfpc *pfpfpc; /* pointer to... */ pfpfpc a[N]; /* array of... */</pre><li>Use the<TT>cdecl</TT> program,which turns English into C and vice versa.Youprovidea longhand description of the type you want,and <TT>cdecl</TT> responds with the equivalent C declaration:<pre> cdecl> declare a as array of pointer to function returning pointer to function returning pointer to char char *(*(*a[])())()</pre><TT>cdecl</TT> can also explain complicated declarations(yougive ita complicated declarationand it responds with an English description),help with casts,and indicate which set of parentheses the parameters go in(for complicated function definitions, like theoneabove).See question <a href="faqcatccbd.html?sec=resources#tools">18.1</a>.</OL></p><p>C's declarationscan be confusingbecausethey come in two parts:a base type,and a <a href="../../sx1/index.html#declarator"><dfn>declarator</dfn></a>which contains the identifier or name being declared,perhaps along with <TT>*</TT>'s and <TT>[]</TT>'s and <TT>()</TT>'ssaying whether the name isa pointer to, array of, or function returningthe base type,or some combination.<a href="../../decl/modifs.html" rel=subdocument>[footnote]</a>For example, in<pre> char *pc;</pre>the base type is <TT>char</TT>,the identifier is <TT>pc</TT>,and the declarator is <TT>*pc</TT>;this tells usthat <TT>*pc</TT> is a <TT>char</TT>(thisis what``declaration mimics use''means).</p><p>One way tomake senseof complicated C declarationsisby reading them ``inside out,''remembering that <TT>[]</TT> and <TT>()</TT>bind more tightly than <TT>*</TT>.For example, given<pre> char *(*pfpc)();</pre>we can see that <TT>pfpc</TT> is a pointer(the inner <TT>*</TT>)to a function(the <TT>()</TT>)to a pointer(the outer <TT>*</TT>)to <TT>char</TT>.When we later use <TT>pfpc</TT>,the expression<TT>*(*pfpc)()</TT>(the value pointed to by the return valueof a function pointed to by <TT>pfpc</TT>)will bea<TT>char</TT>.</p><p>Another way of analyzing these declarations is to decompose the declarator while composing the description, maintaining the ``declaration mimics use'' relationship:<br><br><pre> <TT>*(*pfpc)()</TT> is a <TT>char</TT> <TT>(*pfpc)()</TT> is a pointer to <TT>char</TT> <TT>(*pfpc)</TT> is a function returning pointer to <TT>char</TT> <TT>pfpc</TT> is a pointer to function returning pointer to <TT>char</TT></pre></p><p>If you'd like to make things clearerwhen declaringcomplicatedtypes like these,you can make the analysis explicitby usinga chain of typedefsas in option2 above.</p><p>The pointer-to-function declarations inthe examples abovehave notincludedparameter type information.When the parameters have complicated types,declarations can <em>really</em> getmessy.(Modern versions of <TT>cdecl</TT> can help here, too.)</p><p>Additional links:<br><br>A message of mine explaining the<!-- beware: relative url --><a href="faqcatca65.html?sec=aryptr#ptrary2">difference between array-of-pointer vs. pointer-to-array declarations</a><br><br>David Anderson's``<a href="../../decl/spiral.anderson.html">Clockwise/Spiral Rule</a>''</p><p>References:K&R2 Sec. 5.12 p. 122<br>ISO Sec. 6.5ff (esp. Sec. 6.5.4)<br>H&S Sec. 4.5 pp. 85-92, Sec. 5.10.1 pp. 149-50<hr><hr><hr><a name="recurfuncp"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../decl/recurfuncp.html"><!-- qtag -->Question 1.22</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I declare a functionthat can returna pointer to a functionof the same type?I'm building a state machine with one functionfor each state, each of which returns a pointer to the function forthe next state.But I can't find a way to declare thefunctions--I seemto need a functionreturning a pointer to a functionreturning a pointer to a functionreturning a pointer to a function...,ad infinitum.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>You can't quite do itdirectly.One way is tohave the function returna generic function pointer(see question <a href="faqcatabdc.html?sec=ptrs#generic">4.13</a>),with some judicious caststo adjust the typesas the pointers are passed around:<pre>typedef int (*funcptr)(); /* generic function pointer */typedef funcptr (*ptrfuncptr)(); /* ptr to fcn returning g.f.p. */funcptr start(), stop();funcptr state1(), state2(), state3();void statemachine(){ ptrfuncptr state = start; while(state != stop) state = (ptrfuncptr)(*state)();}funcptr start(){ return (funcptr)state1;}</pre>(The second <TT>ptrfuncptr</TT> typedef hides some particularly darksyntax;without it,the <TT>state</TT> variablewould have to be declared as <TT>funcptr (*state)()</TT>and the call would contain a bewildering cast of the form<TT>(funcptr (*)())(*state)()</TT>.)</p><p>Another way(sugestedbyPaul Eggert,Eugene Ressler,Chris Volpe,and perhaps others)is tohaveeach functionreturn a structurecontaining onlya pointer to a function returningthat structure:<pre>struct functhunk { struct functhunk (*func)();};struct functhunk start(), stop();struct functhunk state1(), state2(), state3();void statemachine(){ struct functhunk state = {start}; while(state.func != stop) state = (*state.func)();}struct functhunk start(){ struct functhunk ret; ret.func = state1; return ret;}</pre>(Note that these examples usethe older, explicit styleof calling via function pointers;see question <a href="faqcatabdc.html?sec=ptrs#funccall">4.12</a>.See also question <a href="faqcatd3c2.html?sec=decl#pfitypedef">1.17</a>.)<hr><hr><hr><a name="dynarray"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../decl/dynarray.html"><!-- qtag -->Question 1.23</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Can I declare a local array(or parameter array)of a size matching a passed-in array,or set by another parameter?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Historically, you couldn't,but in C99(and in some pre-C99 compilers with extensions)you can.See questions<a href="faqcatca65.html?sec=aryptr#dynlocarys">6.15</a> and <a href="faqcatca65.html?sec=aryptr#ary2dfunc2">6.19</a>.<hr><hr><hr><a name="extarraysize"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../decl/extarraysize.html"><!-- qtag -->Question 1.24</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I have an <TT>extern</TT> arraywhich is definedinone file,and used in another:<pre><I>file1.c:</I> <I>file2.c:</I>int array[] = {1, 2, 3}; extern int array[];</pre>Why doesn't <TT>sizeof</TT> work on<TT>array</TT> in <TT>file2.c</TT>?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>An <TT>extern</TT> array of unspecified sizeis an incomplete type; you cannot apply <TT>sizeof</TT> to it.<TT>sizeof</TT> operates at compile time,andthere is no way for it to learn the size of anarraywhich is defined in another file.</p><p>You have three options:<OL><li>Declare a companion variable,containing the size of the array,defined and initialized (with <TT>sizeof</TT>)in the same source file where the array is defined:<pre><I>file1.c:</I> <I>file2.c:</I>int array[] = {1, 2, 3}; extern int array[];int arraysz = sizeof(array); extern int arraysz;</pre>(See also question <a href="faqcatca65.html?sec=aryptr#arraynels">6.23</a>.)<li><TT>#define</TT> a manifest constantfor the sizesothatit can be used consistently in the definitionand the <TT>extern</TT> declaration:<pre><I>file1.h:</I>#define ARRAYSZ 3extern int array[ARRAYSZ];<I>file1.c:</I> <I>file2.c:</I>#include "file1.h" #include "file1.h"int array[ARRAYSZ];</pre><li>Usesome sentinel value(typically <TT>0</TT>, <TT>-1</TT>, or <TT>NULL</TT>)inthe array's last element,sothat code can determine the endwithout an explicit size indication:<pre><I>file1.c:</I> <I>file2.c:</I>int array[] = {1, 2, 3, -1}; extern int array[];</pre></OL>(Obviously,the choice will depend to some extenton whether the array was already being initialized;if it was,option 2 is poor.)</p><p>See also question<a href="faqcatca65.html?sec=aryptr#aryparmsize">6.21</a>.</p><p>References:H&S Sec. 7.5.2 p. 195<hr><hr><hr><a name="implfdecl"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../decl/implfdecl.html"><!-- qtag -->Question 1.25</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>My compiler is complainingabout an invalid redeclaration of a function,but I only define it onceand call it once.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Functions which are called without a declaration in scope,perhaps because the first call precedes the function's definition,are assumedto be declared asif by:<pre> extern int f();</pre>That is,an undeclared function is assumed to return <TT>int</TT>,and to accept an unspecified number of arguments(though there must be a fixed number of themand none may be ``narrow'').If the function is later defined otherwise,the compiler complains about the discrepancy.Functions returning other than <TT>int</TT>,or accepting any ``narrow'' arguments,or accepting a variable number of arguments,must all be declared before they are called.(And it's by all meanssafest to declare all functions,so that function prototypes cancheck that arguments are passed correctly.)</p><p>Another possible source of this problem is that the function has the samename asanotherone declared insome header file.</p><p>See also questions<a href="faqcat7d4b.html?sec=ansi#argpromos">11.3</a>and <a href="faqcat744e.html?sec=varargs#protos">15.1</a>.</p><p>References:K&R1 Sec. 4.2 p. 70<br>K&R2 Sec. 4.2 p. 72<br>ISO Sec. 6.3.2.2<br>H&S Sec. 4.7 p. 101<hr><hr><hr><a name="main"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../decl/main.html"><!-- qtag -->Question 1.25b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>What's the right declaration for <TT>main</TT>?<br>Is <TT>void main()</TT> correct?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>See questions <a href="faqcat7d4b.html?sec=ansi#maindecl">11.12a</a>through<a href="faqcat7d4b.html?sec=ansi#voidmainbooks">11.15</a>.(But no, it's not correct.)<hr><hr><hr><a name="argpromo"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../decl/argpromo.html"><!-- qtag -->Question 1.26</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>My compiler is complaining about mismatched function prototypeswhich look fine to me.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>See question <a href="faqcat7d4b.html?sec=ansi#argpromos">11.3</a>.<hr><hr><hr><a name="headerglom"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../decl/headerglom.html"><!-- qtag -->Question 1.27</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I'm getting strangesyntax errorson the very firstdeclaration ina file,but it looks fine.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>See question <a href="faqcat204f.html?sec=cpp#headerglom">10.9</a>.<hr><hr><hr><a name="bigdatastr"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../decl/bigdatastr.html"><!-- qtag -->Question 1.28</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>My compiler isn't letting me declare a big arraylike<pre>double array[256][256];</pre></p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>See question <a href="faqcatea63.html?sec=osdep#bigdatastr">19.23</a>,and maybe <a href="faqcatbafd.html?sec=malloc#sizewrap">7.16</a>.<hr><hr><hr><a name="namespace"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../decl/namespace.html"><!-- qtag -->Question 1.29</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I determinewhich identifiers are safe for me to useand which are reserved?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Namespace management can be a sticky issue.The problem--which isn't alwaysobvious--is that you don't wantto pick identifiers already in use by the implementation,such thatyouget``multiply defined'' errorsor--even worse--quietlyreplaceone of the implementation's symbolsandbreakeverything.You also want some guarantee that later releaseswon't usurp namesyou're legitimately using.<a href="../../decl/internal.html" rel=subdocument>[footnote]</a>(Few things are more frustratingthan taking a debugged, working, production program,recompiling it under a new release of a compiler,and having the build faildue to namespace or other problems.)Therefore,the ANSI/ISO C Standard contains rather elaborate definitionscarving out distinct namespace subsetsfor the user and the implementation.</p><p>To make sense of ANSI's rules,andbefore we can say whether a given identifier is reserved,we must understand three attributes ofthe identifier:its scope, namespace, and linkage.</p><p>There are four kinds of scope(regions over which anidentifier's declaration is in effect)in C:function,file,block,andprototype.(The fourthoneexists only in the parameter listsof function prototype declarations;see also question <a href="faqcat7d4b.html?sec=ansi#structinproto">11.5</a>.)</p><p>There are four different kinds of namespaces,for:<UL><li>labels(i.e. <TT>goto</TT> targets);<li>tags(names of structures, unions,andenumerations;thesethreearen't separate even though they theoretically could be);<li>structure/union members(one namespace per structure or union);and<li>everything else(functions, variables, typedef names, enumeration constants),termed ``ordinary identifiers'' by the Standard.</UL></p><p>Another set of names(though not termed a ``namespace'' by the Standard)consists of preprocessor macros;these are all expandedbefore the compiler gets around to considering the four formal namespaces.</p><p>The standard defines three kinds of ``linkage'':external, internal, and none.For our purposes,external linkage means global,non-<TT>static</TT> variables and functions(across all source files),internal linkage means <TT>static</TT> variables and functionswith file scope,and``no linkage''refers to local variables,and also things like typedef names and enumeration constants.</p><p>The rules,paraphrased fromANSI Sec. 4.1.2.1,are:</p><UL><li>1.All
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -