📄 faqcatabdc.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 pointers.sgml dated Wed Dec 21 13:07:10 2005 --><!-- corresponding to FAQ list version 4.0 --><html><!-- Mirrored from c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=ptrs by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 07:57:39 GMT --><head><base ><meta name=GENERATOR content="faqproc"><title>Pointers</title></head><body bgcolor="#ffffff"><H1>4. Pointers</H1><a name="goodfor"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ptrs/goodfor.html"><!-- qtag -->Question 4.1</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>What are pointers really good for, anyway?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>They're good forlotsof things,such as:<UL><li>dynamically-allocated arrays(see questions <a href="faqcatca65.html?sec=aryptr#dynarray">6.14</a>and <a href="faqcatca65.html?sec=aryptr#dynmuldimary">6.16</a>)<li>generic access to several similar variables<li>(simulated)by-reference function parameters(see question <a href="faqcatabdc.html?sec=ptrs#passptrinit">4.8</a>and <a href="faqcat38c2.html?sec=misc#multretval">20.1</a>)<li><TT>malloc</TT>'eddata structuresof all kinds,especiallytrees andlinked lists<li>walking overarrays(for example, while parsing strings)<li>efficient,by-reference``copies'' of arraysand structures,especially as function parameters</UL>(Note thatthis is hardly a comprehensive list!)</p><p>See also question <a href="faqcatca65.html?sec=aryptr#practdiff">6.8</a>.<hr><hr><hr><a name="mimic"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ptrs/mimic.html"><!-- qtag -->Question 4.2</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I'm trying to declare a pointer and allocate some space for it,but it'snot working.What's wrong withthis code?<pre>char *p;*p = malloc(10);</pre></p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The pointer you declared is <TT>p</TT>,not <TT>*p</TT>.When you're manipulating the pointer itself(for example when you're setting itto make it point somewhere),you just use the name of the pointer:<pre> p = malloc(10);</pre>It's when you're manipulating the pointed-to memorythat you use <TT>*</TT> as an indirection operator:<pre> *p = 'H';</pre></p><p>(It's easy to make the mistake shown in the question,though,because if you had used the <TT>malloc</TT> call as an initializer in the declarationof alocalvariable,it would have looked like this:<pre> char *p = malloc(10);</pre>When you break an initialized pointer declaration upinto a declaration and a later assignment,you have to remember toremove the <TT>*</TT>.)</p><p>In summary,in an expression,<TT>p</TT> is the pointerand<TT>*p</TT> is what it points to(a <TT>char</TT>, in this example).</p><p>See also questions <a href="faqcatd3c2.html?sec=decl#cdecl1">1.21</a>,<a href="faqcatbafd.html?sec=malloc#malloc1">7.1</a>,<a href="faqcatbafd.html?sec=malloc#ptrvaralloc">7.3c</a>,and<a href="faqcate107.html?sec=charstring#assign">8.3</a>.</p><p>References:CT&P Sec. 3.1 p. 28<hr><hr><hr><a name="unopprec2"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ptrs/unopprec2.html"><!-- qtag -->Question 4.3</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Does <TT>*p++</TT> increment <TT>p</TT>,or what it points to?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The postfix <TT>++</TT> and <TT>--</TT> operatorsessentiallyhave higher precedence than the prefix unary operators.Therefore,<TT>*p++</TT>is equivalent to <TT>*(p++)</TT>;itincrements <TT>p</TT>,and returnsthe valuewhich <TT>p</TT> pointed to before <TT>p</TT> was incremented.To increment the value pointed to by <TT>p</TT>,use <TT>(*p)++</TT>(or perhaps <TT>++*p</TT>,if theevaluationorder of theside effectdoesn't matter).</p><p>References:K&R1 Sec. 5.1 p. 91<br>K&R2 Sec. 5.1 p. 95<br>ISO Sec. 6.3.2, Sec. 6.3.3<br>H&S Sec. 7.4.4 pp. 192-3, Sec. 7.5 p. 193, Secs. 7.5.7,7.5.8 pp. 199-200<hr><hr><hr><a name="explscale"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ptrs/explscale.html"><!-- qtag -->Question 4.4</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I'mtrying to usepointers tomanipulate an array of <TT>int</TT>s.What's wrong with this code?<pre> int array[5], i, *ip; for(i = 0; i < 5; i++) array[i] = i; ip = array; printf("%d\n", *(ip + 3 * sizeof(int)));</pre>I expected the last line to print 3,but it printed garbage.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>You're doing a bit more work than you have to,or should.Pointer arithmetic in C is always automatically scaledby the size of the objects pointed to.What you want to say is simply<pre> printf("%d\n", *(ip + 3)); /* or ip[3] -- see Q <a href="faqcatca65.html?sec=aryptr#aryptrequiv">6.3</a> */</pre>which will print the third element of the array.In code like this,you don't need to worryabout scaling by the size of the pointed-toelements--byattempting to doso explicitly,you inadvertently tried to accessa nonexistent elementpast the end of the array(probably <TT>array[6]</TT> or <TT>array[12]</TT>,depending on <TT>sizeof(int)</TT> on your machine).</p><p>See, however, question <a href="faqcatbafd.html?sec=malloc#noscale">7.19b</a>.</p><p>References:K&R1 Sec. 5.3 p. 94<br>K&R2 Sec. 5.4 p. 103<br>ISO Sec. 6.3.6<br>H&S Sec. 7.6.2 p. 204<hr><hr><hr><a name="castincr"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ptrs/castincr.html"><!-- qtag -->Question 4.5</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Ihavea <TT>char *</TT> pointerthat happens to point tosome <TT>int</TT>s,and I want to step it over them.Why doesn't<pre>((int *)p)++;</pre>work?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>In C, a cast operatordoes not mean``pretend these bits have a different type,and treat them accordingly'';itis a conversion operator,and by definition it yields an rvalue,which cannot be assigned to,or incremented with <TT>++</TT>.(It iseither an accidentor a deliberate but nonstandard extensionif a particular compiler acceptsexpressions such as the above.)Say what you mean:use<pre> p = (char *)((int *)p + 1);</pre>or(since <TT>p</TT> is a <TT>char *</TT>)simply<pre> p += sizeof(int);</pre>or(to be really explicit)<pre> int *ip = (int *)p; p = (char *)(ip + 1);</pre></p><p>Whenpossible,however,you should choose appropriatepointertypesin the first place,rather thantrying to treat one type as another.</p><p>See also question <a href="faqcat5e04.html?sec=strangeprob#ptralign">16.7</a>.</p><p>References:K&R2 Sec. A7.5 p. 205<br>ISO Sec. 6.3.4<br>Rationale Sec. 3.3.2.4<br>H&S Sec. 7.1 pp. 179-80<hr><hr><hr><a name="voidparith"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ptrs/voidparith.html"><!-- qtag -->Question 4.6</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why can't I perform arithmetic on a <TT>void *</TT> pointer?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>See question <a href="faqcat7d4b.html?sec=ansi#voidparith">11.24</a>.<hr><hr><hr><a name="align"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ptrs/align.html"><!-- qtag -->Question 4.7</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I've got some code that's trying to unpack external structures, but it's crashingwith a message about an ``unaligned access.''What does this mean?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>See question <a href="faqcat5e04.html?sec=strangeprob#ptralign">16.7</a>.<hr><hr><hr><a name="passptrinit"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ptrs/passptrinit.html"><!-- qtag -->Question 4.8</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I have a function which accepts,and is supposed to initialize,a pointer:<pre> void f(int *ip) { static int dummy = 5; ip = &dummy; }</pre>But when I call it like this:<pre> int *ip; f(ip);</pre>thepointer in the caller remains unchanged.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Are you sure the function initialized what you thought it did?Remember that arguments in C are passed by value.In the code above,thecalled functionaltersonly the passed copy of the pointer.To make it work as you expect,one fix isto pass the address of the pointer(the functionendsup accepting a pointer-to-a-pointer;in this case,we're essentially simulating pass by reference):<pre> void f(ipp) int **ipp; { static int dummy = 5; *ipp = &dummy; } ... int *ip; f(&ip);</pre></p><p>Another solution is tohave the function return the pointer:<pre> int *f() { static int dummy = 5; return &dummy; } ... int *ip = f();</pre></p><p>See also questions <a href="faqcatabdc.html?sec=ptrs#genericpp">4.9</a>and <a href="faqcatabdc.html?sec=ptrs#passbyref">4.11</a>.<hr><hr><hr><a name="genericpp"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../ptrs/genericpp.html"><!-- qtag -->Question 4.9</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Suppose I want to write a function that takes a generic pointeras an argument and I want to simulate passing it by reference.Can I give the formal parameter type <TT>void **</TT>,and do something like this?<pre> void f(void **); double *dp; f((void **)&dp);</pre></p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Not portably.Code like this may work and is sometimes recommended,but itrelies onall pointer types having the same internal representation(which is common, but not universal;see question <a href="faqcat1f1a.html?sec=null#machexamp">5.17</a>).</p><p>There is no generic pointer-to-pointer type in C.<TT>void *</TT> acts as a generic pointeronly becauseconversions(if necessary)are applied automatically when other pointer typesare assigned to and from <TT>void *</TT>'s;these conversions cannot be performedif an attempt is madeto indirect upon a <TT>void **</TT> valuewhich points ata pointer typeother than <TT>void *</TT>.When you make use of a <TT>void **</TT> pointer value(for instance, when you use the <TT>*</TT> operatorto access the <TT>void *</TT> valueto which the <TT>void **</TT> points),the compiler has no way of knowingwhether that <TT>void *</TT> valuewas once converted from some other pointer type.It must assume that it is nothing more than a <TT>void *</TT>;it cannot perform any implicit conversions.</p><p>In other words,any <TT>void **</TT> value you play withmust be the address of an actual <TT>void *</TT> value somewhere;casts like <TT>(void **)&dp</TT>,though they may shut the compiler up,arenonportable(and may not even do what you want;see also question <a href="faqcat1067.html?sec=lib#qsort2">13.9</a>).If the pointer that the <TT>void **</TT> points tois not a <TT>void *</TT>,and ifithas a different size or representation than a <TT>void *</TT>,thenthe compilerisn't going to be able to access it correctly.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -