📄 faqcatca65.html
字号:
<!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:45 2005 by faqproc version 2.7 --><!-- from source file aryptr.sgml dated Wed Dec 21 12:50:38 2005 --><!-- corresponding to FAQ list version 4.0 --><html><!-- 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:46 GMT --><head><base ><meta name=GENERATOR content="faqproc"><title>Arrays and Pointers</title></head><body bgcolor="#ffffff"><H1>6. Arrays and Pointers</H1><a name="aryptr1"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/aryptr1.html"><!-- qtag -->Question 6.1</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I had the definition <TT>char a[6]</TT> in one source file, and inanother I declared <TT>extern char *a</TT>.Why didn't it work?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>In one source file you defined an array of charactersand in the other you declared a pointer to characters.The declaration <TT>extern char *a</TT>does not declare an array and thereforedoes not match the actualdefinition.The type pointer-to-type-T is not the same asarray-of-type-T.Use <TT>extern char a[]</TT>.</p><p>References:ISO Sec. 6.5.4.2<br>CT&P Sec. 3.3 pp. 33-4, Sec. 4.5 pp. 64-5<hr><hr><hr><a name="aryptr2"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/aryptr2.html"><!-- qtag -->Question 6.2</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>But I heard that <TT>char a[]</TT> was identical to <TT>char *a</TT>.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Not at all.(What you heard has to do with formal parameters to functions;see question<a href="faqcatca65.html?sec=aryptr#aryptrparam">6.4</a>.)Arrays are not pointers,though they are closely related(see question<a href="faqcatca65.html?sec=aryptr#aryptrequiv">6.3</a>)and can be used similarly(see questions<a href="faqcatabdc.html?sec=ptrs#goodfor">4.1</a>,<a href="faqcatca65.html?sec=aryptr#practdiff">6.8</a>,<a href="faqcatca65.html?sec=aryptr#ptrkindofary">6.10</a>,and<a href="faqcatca65.html?sec=aryptr#dynarray">6.14</a>).</p><p>The array declaration<TT>char a[6]</TT>requests that space for six characters be set aside,to be known by the name ``<TT>a</TT>''.That is,there is a location named ``<TT>a</TT>''at which six characters can sit.The pointer declaration<TT>char *p</TT>,on the other hand,requests a place which holds a pointer,to be known by the name ``<TT>p</TT>''.Thispointer can point almost anywhere:to any <TT>char</TT>,or to any contiguous array of <TT>char</TT>s,or nowhere<a href="../../aryptr/anywhere.html" rel=subdocument>[footnote]</a>(see also questions <a href="faqcat1f1a.html?sec=null#null1">5.1</a>and<a href="faqcatd3c2.html?sec=decl#initval">1.30</a>).</p><p>As usual, a picture is worth a thousand words.The declarations<pre> char a[] = "hello"; char *p = "world";</pre>would initialize data structures which could be represented like this:<p><img src="../../aryptr/aryptrstring.gif"><br></p><p>It is useful to realizethat areference like <I fallback=no>x</I><TT>[3]</TT>generates differentcode depending on whether <I fallback=no>x</I> is an array or a pointer.Given the declarations above,when the compiler sees the expression <TT>a[3]</TT>,it emits code to startat the location ``<TT>a</TT>'',move three past it,and fetch the character there.When itsees the expression <TT>p[3]</TT>,it emits code to start at the location ``<TT>p</TT>'',fetch the pointer value there,add three to the pointer,and finally fetch the character pointed to.In other words,<TT>a[3]</TT> is three places past(the start of)the object <em>named</em> <TT>a</TT>,while <TT>p[3]</TT> is three places past the object<em>pointed to</em> by<TT>p</TT>.In the example above,both <TT>a[3]</TT> and <TT>p[3]</TT>happen to be the character 'l',but the compiler gets there differently.(The essential difference is thatthe values ofan array like <TT>a</TT>and a pointer like <TT>p</TT>are computed differently <em>whenever</em> they appear in expressions,whether or not they are being subscripted,as explained further inquestion <a href="faqcatca65.html?sec=aryptr#aryptrequiv">6.3</a>.)See also question<a href="faqcatd3c2.html?sec=decl#strlitinit">1.32</a>.</p><p>References:K&R2 Sec. 5.5 p. 104<br>CT&P Sec. 4.5 pp. 64-5<hr><hr><hr><a name="aryptrequiv"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/aryptrequiv.html"><!-- qtag -->Question 6.3</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>So what is meant by the ``equivalence of pointers and arrays'' in C?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Much of the confusion surroundingarrays andpointers in C can be traced toa misunderstanding ofthis statement.Saying that arrays and pointers are ``equivalent''meansneitherthat they areidenticalnoreveninterchangeable.What it means is that array and pointer arithmetic is definedsuch that a pointer can be conveniently usedto access an arrayor to simulate an array.In other words, as Wayne Throop has put it,it's``pointer <em>arithmetic</em> and array <em>indexing</em>[that]are equivalent in C, pointers and arrays are <em>different</em>.'')</p><p>Specifically,the cornerstone of the equivalence is thiskey definition:<blockquote>A reference to an objectof type array-of-Twhich appears in anexpressiondecays(with three exceptions)into a pointer to its first element;the type of the resultant pointer is pointer-to-T.</blockquote></p><p>That is,whenever an array appears in an expression,the compiler implicitly generates a pointer to the array'sfirst element,just as if the programmer had written <TT>&a[0]</TT>.(The exceptions are when the array is the operand ofa <TT>sizeof</TT>or<TT>&</TT>operator,or is a string literal initializer for a characterarray.<a href="../../aryptr/stringw.html" rel=subdocument>[footnote]</a>See questions<a href="faqcatca65.html?sec=aryptr#arraynels">6.23</a>,<a href="faqcatca65.html?sec=aryptr#aryvsadr">6.12</a>,and<a href="faqcatd3c2.html?sec=decl#strlitinit">1.32</a>,respectively.)</p><p>As a consequence ofthis definition,and in spite of the fact thatthe underlying arrays and pointers are quite different,the compiler doesn't apply the array subscripting operator<TT>[]</TT>that differentlyto arrays and pointers,after all.<a href="../../aryptr/fn28.html" rel=subdocument>[footnote]</a>Given an array <TT>a</TT> and pointer <TT>p</TT>,an expression of the form <TT>a[i]</TT>causes the array to decayinto a pointer,following the rule above,andthen to besubscripted just as would be a pointer variable inthe expression <TT>p[i]</TT>(although the eventual memory accesses will be different,as explained in question<a href="faqcatca65.html?sec=aryptr#aryptr2">6.2</a>).If you were to assign the array's address to the pointer:<pre> p = a;</pre>then <TT>p[3]</TT> and <TT>a[3]</TT> would access the same element.</p><p>Thisharmonyof access explains how pointers can access arrays,serve in their stead as function parameters(see question <a href="faqcatca65.html?sec=aryptr#aryptrparam">6.4</a>),and simulate dynamic arrays(see question <a href="faqcatca65.html?sec=aryptr#dynarray">6.14</a>).</p><p>See also questions <a href="faqcatca65.html?sec=aryptr#practdiff">6.8</a>, <a href="faqcatca65.html?sec=aryptr#ptrkindofary">6.10</a>, and <a href="faqcatca65.html?sec=aryptr#dynarray">6.14</a>.</p><p>References:K&R1 Sec. 5.3 pp. 93-6<br>K&R2 Sec. 5.3 p. 99<br>ISO Sec. 6.2.2.1, Sec. 6.3.2.1, Sec. 6.3.6<br>H&S Sec. 5.4.1 p. 124<hr><hr><hr><a name="aryptrparam"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/aryptrparam.html"><!-- qtag -->Question 6.4</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>If they're so different,thenwhyare array and pointer declarations interchangeable asfunction formal parameters?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>It'ssupposed to bea convenience.</p><p>Since arrays decay immediately into pointers,an array is never actually passed to a function.You canpretend thata function receives an array asaparameter,andillustrate itby declaring thecorrespondingparameter as an array:<pre> void f(char a[]) { ... }</pre>Interpreted literally,this declaration would have no use,sothe compiler turnsaround and pretendsthat you'd written a pointer declaration,since that's what the function will in fact receive:<pre> void f(char *a) { ... }</pre>There's nothingparticularlywrong with talking about a functionas if it``receives'' an array,ifthe function is traditionally used to operate on arrays,or ifthe parameter is naturally treated within the function as an array.</p><p>This conversionof array-like declarators into pointersholds only within functionformal parameter declarations,nowhere else.If the conversion bothers you,you're under no compulsionto make use ofit;many programmershave concluded that the confusion it causes outweighsthe small advantage of having the declaration ``look like'' the callor the uses within the function.(Note that the conversion happens only once;something like <TT>char a2[][]</TT> won't work.See questions <a href="faqcatca65.html?sec=aryptr#pass2dary">6.18</a>and<a href="faqcatca65.html?sec=aryptr#ary2dfunc2">6.19</a>.)</p><p>See also question<a href="faqcatca65.html?sec=aryptr#aryparmsize">6.21</a>.</p><p>References:K&R1 Sec. 5.3 p. 95, Sec. A10.1 p. 205<br>K&R2 Sec. 5.3 p. 100, Sec. A8.6.3 p. 218, Sec. A10.1 p. 226<br>ISO Sec. 6.5.4.3, Sec. 6.7.1, Sec. 6.9.6<br>H&S Sec. 9.3 p. 271<br>CT&P Sec. 3.3 pp. 33-4<br>Dennis Ritchie, ``The Development of the C Language''<hr><hr><hr><a name="arypbref"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/arypbref.html"><!-- qtag -->Question 6.4b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>So arrays are passed by reference,even though the rest of C uses pass by value?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>That's one way of thinking about it.See question <a href="faqcatabdc.html?sec=ptrs#passbyref">4.11</a>.<hr><hr><hr><a name="arrayassign"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/arrayassign.html"><!-- qtag -->Question 6.5</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why can'tIdo something like this?<pre> extern char *getpass(); char str[10]; str = getpass("Enter password: ");</pre></p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Arrays are ``second-class citizens''in C;one upshot of this prejudice is that you cannot assign to them(see also question <a href="faqcatca65.html?sec=aryptr#arraylval">6.7</a>).When you need to copy the contents of one array to another,you must do so explicitly.In the case of <TT>char</TT> arrays,the <TT>strcpy</TT> routine is usually appropriate:<pre> strcpy(str, getpass("Enter password: "));</pre></p><p>(When you want topass arrays aroundwithout copying them,you can use pointers and simple assignment.See also question <a href="faqcatabdc.html?sec=ptrs#goodfor">4.1</a>.)</p><p>See also question <a href="faqcate107.html?sec=charstring#stringeq">8.2</a>.</p><p>References:ISO Sec. 6.2.2.1<br>H&S Sec. 7.9.1 pp. 221-2<hr><hr><hr><a name="aryparmasgn"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/aryparmasgn.html"><!-- qtag -->Question 6.6</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>If you can't assign to arrays,thenhow can<pre> int f(char str[]) { if(str[0] == '\0') str = "none"; ... }</pre>work?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>In this code,<TT>str</TT> is a function parameter,so its declaration is rewritten by the compileras described in question <a href="faqcatca65.html?sec=aryptr#aryptrparam">6.4</a>.In other words, <TT>str</TT> <em>is</em> a pointer(of type <TT>char *</TT>),and it is legal toassign toit.<hr><hr><hr><a name="aryasgn3"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/aryasgn3.html"><!-- qtag -->Question 6.6b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>And what about this?Isn't this an array assignment?<pre> char a[] = "Hello, world!\n";</pre></p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>No, that's an initialization.You <em>are</em> allowed to initialize arrays when you define them.<hr><hr><hr><a name="arraylval"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/arraylval.html"><!-- qtag -->Question 6.7</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How can an array be an lvalue, if you can't assign to it?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The term ``lvalue'' doesn't quite mean``something you can assign to'';a better definition is``something that has a <B>l</B>ocation(in memory).''<a href="../../aryptr/lvalue.html" rel=subdocument>[footnote]</a>The ANSI/ISO C Standard goes on to define a``modifiable lvalue'';an arrayis not a modifiable lvalue.See also question <a href="faqcatca65.html?sec=aryptr#arrayassign">6.5</a>.</p><p>References:ISO Sec. 6.2.2.1<br>Rationale Sec. 3.2.2.1<br>H&S Sec. 7.1 p. 179<hr><hr><hr><a name="practdiff"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../aryptr/practdiff.html"><!-- qtag -->Question 6.8</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Practically speaking,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -