📄 faqcatbafd.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 malloc.sgml dated Wed Dec 21 13:50:44 2005 --><!-- corresponding to FAQ list version 4.0 --><html><!-- Mirrored from c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=malloc by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 07:57:52 GMT --><head><base ><meta name=GENERATOR content="faqproc"><title>Memory Allocation</title></head><body bgcolor="#ffffff"><H1>7. Memory Allocation</H1><a name="malloc1"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../malloc/malloc1.html"><!-- qtag -->Question 7.1</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why doesn'tthis fragmentwork?<pre> char *answer; printf("Type something:\n"); gets(answer); printf("You typed \"%s\"\n", answer);</pre></p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The pointer variable <TT>answer</TT>,which is handed to<TT>gets()</TT>as the location into which the response should bestored,has not been set topoint to any valid storage.It isan uninitialized variable, just as is the variable <TT>i</TT> in<pre> int i; printf("i = %d\n", i);</pre>That is,in the first piece of code,we cannot say where the pointer <TT>answer</TT>points,just as we cannot say what value <TT>i</TT> will have in the second.(Since local variables are not initialized,and typically contain garbage,it is not even guaranteed that <TT>answer</TT> starts out as anull pointer.See questions<a href="faqcatd3c2.html?sec=decl#initval">1.30</a>and<a href="faqcat1f1a.html?sec=null#null1">5.1</a>.)</p><p>The simplest way to correctthe question-asking programis touse a local array, instead of apointer, and let the compilerworry aboutallocation:<pre>#include <stdio.h>#include <string.h>char answer[100], *p;printf("Type something:\n");fgets(answer, sizeof answer, stdin);if((p = strchr(answer, '\n')) != NULL) *p = '\0';printf("You typed \"%s\"\n", answer);</pre></p>This example also uses <TT>fgets()</TT>instead of <TT>gets()</TT>,so thatthe end of the arraycannot be overwritten.(See question<a href="faqcat1d60.html?sec=stdio#getsvsfgets">12.23</a>.Unfortunately for this example,<TT>fgets()</TT> does not automatically delete the trailing <TT>\n</TT>,as<TT>gets()</TT> would.)It would also be possible to use <TT>malloc()</TT> to allocate the<TT>answer</TT>buffer,and to parameterize the buffer size(with something like <TT>#define ANSWERSIZE 100</TT> ).<hr><hr><hr><a name="malloc2"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../malloc/malloc2.html"><!-- qtag -->Question 7.2</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I can't get <TT>strcat</TT> to work.I tried<pre> char *s1 = "Hello, "; char *s2 = "world!"; char *s3 = strcat(s1, s2);</pre>but I got strange results.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>As in question <a href="faqcatbafd.html?sec=malloc#malloc1">7.1</a>,the main problem hereis that space for the concatenated result isnot properly allocated.C does not provide an automatically-managed string type.C compilers allocate memoryonly for objects explicitlymentioned in the source code(in the case of strings,thisincludes character arrays and string literals).The programmer mustarrangefor sufficient space forthe results of run-time operations such as string concatenation,typically by declaring arrays, or by calling <TT>malloc</TT>.</p><p><TT>strcat</TT> performs no allocation;the second string is appended to the first one,in place.The first(destination)string mustbe writable andhave enough roomfor the concatenated result.Therefore, one fix would be to declare the first string asanarray:<pre> char s1[20] = "Hello, ";</pre>(In production code,of course,we wouldn't use magic numbers like ``20'';we'd use more robust mechanismsto guarantee sufficient space.)</p><p>Since <TT>strcat</TT>returns the value of its first argument(<TT>s1</TT>, in this case),the variable <TT>s3</TT>inthe question aboveissuperfluous;after the call to <TT>strcat</TT>,<TT>s1</TT> contains the result.</p><p>The original call to <TT>strcat</TT> in the questionactually hastwo problems:the string literal pointed to by <TT>s1</TT>,besides not being big enough for any concatenated text,is not necessarily writableat all.See question<a href="faqcatd3c2.html?sec=decl#strlitinit">1.32</a>.</p><p>References:CT&P Sec. 3.2 p. 32<hr><hr><hr><a name="attitude"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../malloc/attitude.html"><!-- qtag -->Question 7.3</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>But theman pagefor <TT>strcat</TT> says thatit takes two <TT>char *</TT>'s as arguments.How amI supposed to know to allocate things?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>In general, when using pointers you<em>always</em>have to considermemory allocation,if onlyto make sure that the compiler is doing it for you.If alibrary function's documentation does not explicitly mention allocation,it is usually the caller's problem.</p><p>The Synopsis section at the top of aUnix-styleman pageor in the ANSI C standardcan be misleading.The code fragments presented there are closer to the functiondefinitions used by an implementorthan the invocations used by the caller.In particular, many functions which accept pointers(e.g. to structures or strings)are usually called witha pointer tosome object(a structure, or an array--see questions<a href="faqcatca65.html?sec=aryptr#aryptrequiv">6.3</a> and<a href="faqcatca65.html?sec=aryptr#aryptrparam">6.4</a>)which the callerhas allocated.Other common examples are<TT>time</TT>(see question <a href="faqcat1067.html?sec=lib#curtime">13.12</a>)and<TT>stat</TT>.<hr><hr><hr><a name="lucky"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../malloc/lucky.html"><!-- qtag -->Question 7.3b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I just tried the code<pre>char *p;strcpy(p, "abc");</pre>and it worked.How?Why didn't it crash?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>You got lucky, I guess.The memoryrandomlypointed to bythe uninitialized pointer <TT>p</TT>happened to be writable by you,and apparently was not already in use for anything vital.See also question <a href="faqcat7d4b.html?sec=ansi#experiment">11.35</a>.</p><p>Additional links:<a href="faqcatbafd.html?sec=malloc#badalloc">longer explanation</a>,<a href="faqcatbafd.html?sec=malloc#badalloc2">another longer explanation</a><hr><hr><hr><a name="ptrvaralloc"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../malloc/ptrvaralloc.html"><!-- qtag -->Question 7.3c</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>How much memory does a pointer variable allocate?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>That's a pretty misleading question.When you declarea pointer variable,as in<pre> char *p;</pre>you(or, more properly, the compiler)have allocated onlyenough memory to hold the pointer itself;that is,in this caseyou have allocated <TT>sizeof(char *)</TT>bytes of memory.But you havenot yet allocated <em>any</em>memory for the pointer to point to.See also questions <a href="faqcatbafd.html?sec=malloc#malloc1">7.1</a> and <a href="faqcatbafd.html?sec=malloc#malloc2">7.2</a>.<hr><hr><hr><a name="linebfdur"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../malloc/linebfdur.html"><!-- qtag -->Question 7.4</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I'mreadinglines from a file into anarray,with this code:<pre> char linebuf[80]; char *lines[100]; int i; for(i = 0; i < 100; i++) { char *p = fgets(linebuf, 80, fp); if(p == NULL) break; lines[i] = p; }</pre>Why do all the lines end up containing copies of the last line?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>You have only allocated memory for one line,<TT>linebuf</TT>.Each time you call <TT>fgets</TT>,the previous line is overwritten.<TT>fgets</TT> doesn't do any memory allocation:unless it reaches EOF(or encounters an error),the pointer it returnsis the same pointeryou handed it as its first argument(in this case, a pointer to your single <TT>linebuf</TT> array).</p><p>To make code like this work,you'll need to allocate memory for each line.See question <a href="faqcat38c2.html?sec=misc#ragged">20.2</a> for an example.</p><p>References:K&R1 Sec. 7.8 p. 155<br>K&R2 Sec. 7.7 pp. 164-5<br>ISO Sec. 7.9.7.2<br>H&S Sec. 15.7 p. 356<hr><hr><hr><a name="retaggr"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../malloc/retaggr.html"><!-- qtag -->Question 7.5a</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>I have a function that is supposed to return a string,but when it returns to its caller,the returned string is garbage.</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>Whenever a function returns a pointer,makesure that the pointed-to memoryisproperlyallocated.For example,make sure you have <em>not</em> donesomething like<pre><br> #include <stdio.h><br> char *itoa(int n) { char retbuf[20]; /* WRONG */ sprintf(retbuf, "%d", n); return retbuf; /* WRONG */ }</pre>When a function returns,itsautomatic, localvariablesare discarded,so the returned pointer in this case is invalid(it points to an array that no longer exists).</p><p>One fixwould be to declare the return buffer as<pre> static char retbuf[20];</pre>This fix is imperfect,since a function using static data is not reentrant.Furthermore,successive calls to this version of <TT>itoa</TT> keep overwriting the same return buffer:the caller won't be ableto call it several timesand keepall thereturn values aroundsimultaneously.</p><p>See also questions<a href="faqcatbafd.html?sec=malloc#retaggr2">7.5b</a>,<a href="faqcat1d60.html?sec=stdio#sprintfsize">12.21</a>,and<a href="faqcat38c2.html?sec=misc#multretval">20.1</a>.</p><p>References:ISO Sec. 6.1.2.4<hr><hr><hr><a name="retaggr2"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../malloc/retaggr2.html"><!-- qtag -->Question 7.5b</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>So what's the right way to return a stringor other aggregate?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>The returned pointer should beto a statically-allocated buffer(as in the answer to question <a href="faqcatbafd.html?sec=malloc#retaggr">7.5a</a>),or toa buffer passed in by the caller,ortomemory obtained with <TT>malloc</TT>,but<em>not</em>to a local(automatic)array.</p><p>For example,to have the caller pass space for the result:<pre> char *itoa(int n, char *retbuf) { sprintf(retbuf, "%d", n); return retbuf; } ... char str[20]; itoa(123, str);</pre></p><p>To use <TT>malloc</TT>:<pre> #include <stdlib.h> char *itoa(int n) { char *retbuf = malloc(20); if(retbuf != NULL) sprintf(retbuf, "%d", n); return retbuf; } ... char *str = itoa(123);</pre>(In this lastcase,the caller must remember to <TT>free</TT>the returned pointer when it is no longer needed.)</p><p>See also question<a href="faqcat38c2.html?sec=misc#multretval">20.1</a>.</p><p>Additional links:<a href="../../malloc/sd2.html" rel=subdocument>further reading</a><hr><hr><hr><a name="decl"><h1>comp.lang.c FAQ list<font color=blue>·</font><a href="../../malloc/decl.html"><!-- qtag -->Question 7.6</a></h1><p><font face=Helvetica size=8 color=blue><b>Q:</b></font>Why am I getting``warning: assignment of pointer from integer lacks a cast''for calls to <TT>malloc</TT>?</p><p><hr><p><font face=Helvetica size=8 color=blue><b>A:</b></font>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -