📄 faqcatca65.html
字号:
#define Arrayaccess(a, i, j) ((a)[(i) * ncolumns + (j)])</pre>couldhide the explicit calculation,but invoking itwould requireparentheses and commaswhich wouldn't look exactly likeconventional Cmultidimensional array syntax,andthe macrowould needaccess to at least one of the dimensions,as well.See also question <a href="faqcatca65.html?sec=aryptr#ary2dfunc2">6.19</a>.)</p><p>Yet another optionis touse pointers to arrays:<pre> int (*array4)[NCOLUMNS] = malloc(nrows * sizeof(*array4));</pre>or even<pre> int (*array5)[NROWS][NCOLUMNS] = malloc(sizeof(*array5));</pre>but the syntax starts getting horrific(accesses to <TT>array5</TT> look like <TT>(*array5)[i][j]</TT>),andat most one dimension may be specified at run time.</p><p>With all of these techniques,you may of course need to remember to free the arrayswhen they are no longer needed;in the case of <TT>array1</TT> and <TT>array2</TT>this takes several steps(see also question <a href="faqcatbafd.html?sec=malloc#freeforall">7.23</a>):<pre> for(i = 0; i < nrows; i++) free((void *)array1[i]); free((void *)array1); free((void *)array2[0]); free((void *)array2);</pre>Also,you cannot necessarily intermix dynamically-allocatedarrays with conventional, statically-allocated ones(see question<a href="faqcatca65.html?sec=aryptr#ary2dfunc3">6.20</a>,and also question<a href="faqcatca65.html?sec=aryptr#pass2dary">6.18</a>).</p><p>Finally, in C99 you can use a variable-length array.</p><p>All ofthese techniques can also be extended to three or moredimensions.Here is a three-dimensional version of the first technique(which, like the rest of the fragments presented here,requires error-checking before being used in a real program):<pre> int ***a3d = (int ***)malloc(xdim * sizeof(int **)); for(i = 0; i < xdim; i++) { a3d[i] = (int **)malloc(ydim * sizeof(int *)); for(j = 0; j < ydim; j++) a3d[i][j] = (int *)malloc(zdim * sizeof(int)); }</pre></p><p>See also question <a href="faqcat38c2.html?sec=misc#ragged">20.2</a>.</p><p>References:C9X Sec. 6.5.5.2<hr><hr><hr><a name="non0based"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/non0based.html"><!-- qtag -->Question 6.17</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Here's a neat trick: if I write<pre> int realarray[10]; int *array = &realarray[-1];</pre>I can treat <TT>array</TT> as if it were a 1-based array.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Although this technique is attractive(and was used inold editionsofthe book<I>Numerical Recipes in C</I>),it is not strictly conforming to the C Standard.Pointer arithmeticis definedonly as long as the pointer pointswithin the same allocated block of memory,or to the imaginary ``terminating'' elementone past it;otherwise,the behavior is undefined,<em>even if the pointer is not dereferenced</em>.The code abovecomputes a pointer to memory before the beginning of <TT>realarray</TT>andcould fail if,while subtracting the offset,an illegaladdress were generated(perhaps because the address triedto ``wrap around''past the beginning of some memory segment).</p><p>Additional links:<a href="../../aryptr/Virginia.html" rel=subdocument>“Yes, Virginia”</a></p><p>References:K&R2 Sec. 5.3 p. 100, Sec. 5.4 pp. 102-3, Sec. A7.7 pp. 205-6<br>ISO Sec. 6.3.6<br>Rationale Sec. 3.2.2.3<hr><hr><hr><a name="pass2dary"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/pass2dary.html"><!-- qtag -->Question 6.18</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>My compiler complained when I passed a two-dimensional array to afunction expecting a pointer to a pointer.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The rule(see question <a href="faqcatca65.html?sec=aryptr#aryptrequiv">6.3</a>)by which arrays decay into pointers is<em>not</em>applied recursively.(Once the rule has been applied once,the result is a pointer to which the rule no longer applies.)An array of arrays (i.e. a two-dimensional array in C) decaysinto a pointer to an array, not a pointer to a pointer.Pointers to arrays can be confusing,and must be treated carefully;see also question <a href="faqcatca65.html?sec=aryptr#ptrtoarray">6.13</a>.</p><p>If you are passing a two-dimensional array to a function:<pre> int array[NROWS][NCOLUMNS]; f(array);</pre>the function's declarationmust match:<pre> void f(int a[][NCOLUMNS]) { ... }</pre>or<pre> void f(int (*ap)[NCOLUMNS]) /* ap is a pointer to an array */ { ... }</pre>In the first declaration,the compiler performs the usualimplicit parameter rewritingof ``array of array''to ``pointer to array''(see questions<a href="faqcatca65.html?sec=aryptr#aryptrequiv">6.3</a>and<a href="faqcatca65.html?sec=aryptr#aryptrparam">6.4</a>);in the second form the pointer declaration is explicit.Since the called function does not allocate space for the array,it does not need to know the overall size,so the number ofrows,<TT>NROWS</TT>,can be omitted.Thewidthof the array is still important,so thecolumndimension<TT>NCOLUMNS</TT>(and, for three- or more dimensional arrays,the intervening ones)must beretained.</p><p>If a function is already declared as accepting apointer to a pointer,it isalmost certainlymeaninglessto pass a two-dimensional array directly to it.An intermediate pointer would have to be used when attempting to call itwith a two-dimensional array:<pre> extern g(int **ipp); int *ip = &array[0][0]; g(&ip); /* PROBABLY WRONG */</pre>butthis usage ismisleadingand almost certainlyincorrect,since the array has been ``flattened''(its shape has been lost).</p><p>See also questions <a href="faqcatca65.html?sec=aryptr#aryvsadr">6.12</a> and <a href="faqcatca65.html?sec=aryptr#dynlocarys">6.15</a>.</p><p>References:K&R1 Sec. 5.10 p. 110<br>K&R2 Sec. 5.9 p. 113<br>H&S Sec. 5.4.3 p. 126<hr><hr><hr><a name="ary2dfunc2"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/ary2dfunc2.html"><!-- qtag -->Question 6.19</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How do I write functions which accept two-dimensional arrayswhen the width is not known at compile time?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>It's notalwayseasy.One way is to pass in a pointer to the <TT>[0][0]</TT> element, alongwith the two dimensions, and simulate array subscripting ``by hand'':<pre> void f2(int *aryp, int nrows, int ncolumns) { ... array[i][j] is accessed as aryp[i * ncolumns + j] ... }</pre>Note that the correct expressionfor manual subscriptinginvolves <TT>ncolumns</TT>(the ``width'' of each row),not <TT>nrows</TT>(the <em>number</em> of rows);it's easy to get thisbackwards.</p><p>This function could be called with the <TT>array</TT> fromquestion<a href="faqcatca65.html?sec=aryptr#pass2dary">6.18</a> as<pre> f2(&array[0][0], NROWS, NCOLUMNS);</pre></p><p>It must be noted,however,that a program which performsmultidimensional array subscripting ``by hand''in this wayis not in strict conformancewith the ANSI C Standard;according toan official interpretation,the behavior of accessing<TT>(&array[0][0])[x]</TT>is not definedfor <TT>x >= NCOLUMNS</TT>.</p><p>C99 allows variable-length arrays,and once compilers which accept C99's extensions become widespread,VLA'swill probably become the preferred solution.(<TT>gcc</TT> has supported variable-sized arrays for some time.)</p><p>When you want to be able to use a functionon multidimensional arrays of various sizes,one solution is to simulate all the arrays dynamically,as in question <a href="faqcatca65.html?sec=aryptr#dynmuldimary">6.16</a>.</p><p>See also questions<a href="faqcatca65.html?sec=aryptr#pass2dary">6.18</a>,<a href="faqcatca65.html?sec=aryptr#ary2dfunc3">6.20</a>,and<a href="faqcatca65.html?sec=aryptr#dynlocarys">6.15</a>.</p><p>References:ISO Sec. 6.3.6<br>C9X Sec. 6.5.5.2<hr><hr><hr><a name="ary2dfunc3"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/ary2dfunc3.html"><!-- qtag -->Question 6.20</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can I use statically- and dynamically-allocatedmultidimensional arrays interchangeably when passing them to functions?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>There is no single perfect method.Given thedeclarations<pre> int array[NROWS][NCOLUMNS]; int **array1; /* ragged */ int **array2; /* contiguous */ int *array3; /* "flattened" */ int (*array4)[NCOLUMNS];<br> int (*array5)[NROWS][NCOLUMNS];</pre>with the pointersinitializedasin the code fragments in question<a href="faqcatca65.html?sec=aryptr#dynmuldimary">6.16</a>,and functions declared as<pre> void f1a(int a[][NCOLUMNS], int nrows, int ncolumns); void f1b(int (*a)[NCOLUMNS], int nrows, int ncolumns); void f2(int *aryp, int nrows, int ncolumns); void f3(int **pp, int nrows, int ncolumns);</pre>where<TT>f1a</TT> and <TT>f1b</TT> accept conventional two-dimensional arrays,<TT>f2</TT> accepts a ``flattened'' two-dimensional array,and<TT>f3</TT> accepts a pointer-to-pointer, simulated array(see also questions<a href="faqcatca65.html?sec=aryptr#pass2dary">6.18</a> and<a href="faqcatca65.html?sec=aryptr#ary2dfunc2">6.19</a>),the following callsshouldwork as expected:<pre> f1a(array, NROWS, NCOLUMNS); f1b(array, NROWS, NCOLUMNS); f1a(array4, nrows, NCOLUMNS); f1b(array4, nrows, NCOLUMNS);<br> f1(*array5, NROWS, NCOLUMNS);<br> f2(&array[0][0], NROWS, NCOLUMNS); f2(*array, NROWS, NCOLUMNS); f2(*array2, nrows, ncolumns); f2(array3, nrows, ncolumns); f2(*array4, nrows, NCOLUMNS);<br> f2(**array5, NROWS, NCOLUMNS);<br> f3(array1, nrows, ncolumns); f3(array2, nrows, ncolumns);</pre>The followingcalls would probably workon most systems,but involve questionable casts,and workonly if the dynamic <TT>ncolumns</TT>matches the static <TT>NCOLUMNS</TT>:<pre> f1a((int (*)[NCOLUMNS])(*array2), nrows, ncolumns); f1a((int (*)[NCOLUMNS])(*array2), nrows, ncolumns); f1b((int (*)[NCOLUMNS])array3, nrows, ncolumns); f1b((int (*)[NCOLUMNS])array3, nrows, ncolumns);</pre></p><p>It will be noticed that only <TT>f2</TT> can conveniently be made to workwith both statically- and dynamically-allocated arrays,thoughit will<em>not</em>work with the traditional``ragged'' array implementation,<TT>array1</TT>.However,it must alsobe noted thatpassing <TT>&array[0][0]</TT>(or, equivalently, <TT>*array</TT>)to <TT>f2</TT>is not strictly conforming;see question<a href="faqcatca65.html?sec=aryptr#ary2dfunc2">6.19</a>.</p><p>If you can understand why all of the above calls work and arewritten as they are,and if you understand why the combinations that are not listedwould not work,then you have a<em>very</em>good understanding of arrays and pointersin C.</p><p>Rather than worrying about all of this,one approach to using multidimensional arrays of various sizesis to make them <em>all</em> dynamic,as in question <a href="faqcatca65.html?sec=aryptr#dynmuldimary">6.16</a>.If there are no static multidimensional arrays--ifall arrays are allocated like <TT>array1</TT> or <TT>array2</TT>in question <a href="faqcatca65.html?sec=aryptr#dynmuldimary">6.16</a>--thenall functions can be written like <TT>f3</TT>.</p><p>Additional links:<a href="../../aryptr/aryptr.c">Sample source code</a>(``torture test'')illustrating all these techniques<hr><hr><hr><a name="aryparmsize"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/aryparmsize.html"><!-- qtag -->Question 6.21</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why doesn't <TT>sizeof</TT> properly report the size of an arraywhen the arrayis a parameter to a function?I have a test routine<pre> f(char a[10]) { int i = sizeof(a); printf("%d\n", i); }</pre>and it prints4, not 10.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The compiler pretends that the array parameter was declared as apointer(that is,in the example,as <TT>char *a</TT>;see question<a href="faqcatca65.html?sec=aryptr#aryptrparam">6.4</a>),and <TT>sizeof</TT> reports the size of the pointer.See also questions<a href="faqcatd3c2.html?sec=decl#extarraysize">1.24</a>and<a href="faqcatbafd.html?sec=malloc#sizeof">7.28</a>.</p><p>References:H&S Sec. 7.5.2 p. 195<hr><hr><hr><a name="extarysize"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/extarysize.html"><!-- qtag -->Question 6.22</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can code in a file where an array is declared as <TT>extern</TT>(i.e. it is defined, and its size determined, in some other file)determine the size of the array?<TT>sizeof</TT> doesn't seem to work.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>See question <a href="faqcatd3c2.html?sec=decl#extarraysize">1.24</a>.<hr><hr><hr><a name="arraynels"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/arraynels.html"><!-- qtag -->Question 6.23</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I want to know how many elements are in an array,but <TT>sizeof</TT> yields the size in bytes.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Simply divide the size of the entire array by the size of one element:<pre> int array[] = {1, 2, 3}; int narray = sizeof(array) / sizeof(array[0]);</pre></p><p>References:ISO Sec. 6.3.3.4<hr><hr><hr><a name="arybits"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/arybits.html"><!-- qtag -->Question 6.24</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Is there a way to have an array of bits?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>No.But see question <a href="faqcat38c2.html?sec=misc#bitsets">20.8</a>.<hr><hr><hr><hr><p>Read sequentially:<a href="faqcat1f1a.html?sec=null" rev=precedes>prev</a><a href="faqcatbafd.html?sec=malloc" 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="../../aryptr/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=aryptr by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 07:57:52 GMT --></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -