⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 library_3.html

📁 Linux程序员的工作手册
💻 HTML
📖 第 1 页 / 共 5 页
字号:
If you are using an old-fashioned non-ANSI C compiler, all the obstack"functions" are actually defined only as macros.  You can call thesemacros like functions, but you cannot use them in any other way (forexample, you cannot take their address).<P>Calling the macros requires a special precaution: namely, the firstoperand (the obstack pointer) may not contain any side effects, becauseit may be computed more than once.  For example, if you write this:<P><PRE>obstack_alloc (get_obstack (), 4);</PRE><P>you will find that <CODE>get_obstack</CODE> may be called several times.If you use <CODE>*obstack_list_ptr++</CODE> as the obstack pointer argument,you will get very strange results since the incrementation may occurseveral times.<P>In ANSI C, each function has both a macro definition and a functiondefinition.  The function definition is used if you take the address of thefunction without calling it.  An ordinary call uses the macro definition bydefault, but you can request the function definition instead by writing thefunction name in parentheses, as shown here:<P><PRE>char *x;void *(*funcp) ();/* Use the macro.  */x = (char *) obstack_alloc (obptr, size);/* Call the function.  */x = (char *) (obstack_alloc) (obptr, size);/* Take the address of the function.  */funcp = obstack_alloc;</PRE><P>This is the same situation that exists in ANSI C for the standard libraryfunctions.  See section <A HREF="library_1.html#SEC10" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_1.html#SEC10">Macro Definitions of Functions</A>.<P><STRONG>Warning:</STRONG> When you do use the macros, you must observe theprecaution of avoiding side effects in the first operand, even in ANSIC.<P>If you use the GNU C compiler, this precaution is not necessary, becausevarious language extensions in GNU C permit defining the macros so as tocompute each argument only once.<P><A NAME="IDX183"></A><A NAME="IDX184"></A><H3><A NAME="SEC39" HREF="library_toc.html#SEC39" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC39">Growing Objects</A></H3><P>Because storage in obstack chunks is used sequentially, it is possible tobuild up an object step by step, adding one or more bytes at a time to theend of the object.  With this technique, you do not need to know how muchdata you will put in the object until you come to the end of it.  We callthis the technique of <DFN>growing objects</DFN>.  The special functionsfor adding data to the growing object are described in this section.<P>You don't need to do anything special when you start to grow an object.Using one of the functions to add data to the object automaticallystarts it.  However, it is necessary to say explicitly when the object isfinished.  This is done with the function <CODE>obstack_finish</CODE>.<P>The actual address of the object thus built up is not known until theobject is finished.  Until then, it always remains possible that you willadd so much data that the object must be copied into a new chunk.<P>While the obstack is in use for a growing object, you cannot use it forordinary allocation of another object.  If you try to do so, the spacealready added to the growing object will become part of the other object.<P><A NAME="IDX185"></A><U>Function:</U> void <B>obstack_blank</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>, size_t <VAR>size</VAR>)</I><P>The most basic function for adding to a growing object is<CODE>obstack_blank</CODE>, which adds space without initializing it.<P><A NAME="IDX186"></A><U>Function:</U> void <B>obstack_grow</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>, void *<VAR>data</VAR>, size_t <VAR>size</VAR>)</I><P>To add a block of initialized space, use <CODE>obstack_grow</CODE>, which isthe growing-object analogue of <CODE>obstack_copy</CODE>.  It adds <VAR>size</VAR>bytes of data to the growing object, copying the contents from<VAR>data</VAR>.<P><A NAME="IDX187"></A><U>Function:</U> void <B>obstack_grow0</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>, void *<VAR>data</VAR>, size_t <VAR>size</VAR>)</I><P>This is the growing-object analogue of <CODE>obstack_copy0</CODE>.  It adds<VAR>size</VAR> bytes copied from <VAR>data</VAR>, followed by an additional nullcharacter.<P><A NAME="IDX188"></A><U>Function:</U> void <B>obstack_1grow</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>, char <VAR>c</VAR>)</I><P>To add one character at a time, use the function <CODE>obstack_1grow</CODE>.It adds a single byte containing <VAR>c</VAR> to the growing object.<P><A NAME="IDX189"></A><U>Function:</U> void * <B>obstack_finish</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>)</I><P>When you are finished growing the object, use the function<CODE>obstack_finish</CODE> to close it off and return its final address.<P>Once you have finished the object, the obstack is available for ordinaryallocation or for growing another object.<P>When you build an object by growing it, you will probably need to knowafterward how long it became.  You need not keep track of this as you growthe object, because you can find out the length from the obstack justbefore finishing the object with the function <CODE>obstack_object_size</CODE>,declared as follows:<P><A NAME="IDX190"></A><U>Function:</U> size_t <B>obstack_object_size</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>)</I><P>This function returns the current size of the growing object, in bytes.Remember to call this function <EM>before</EM> finishing the object.After it is finished, <CODE>obstack_object_size</CODE> will return zero.<P>If you have started growing an object and wish to cancel it, you shouldfinish it and then free it, like this:<P><PRE>obstack_free (obstack_ptr, obstack_finish (obstack_ptr));</PRE><P>This has no effect if no object was growing.<A NAME="IDX191"></A><P>You can use <CODE>obstack_blank</CODE> with a negative size argument to makethe current object smaller.  Just don't try to shrink it beyond zerolength--there's no telling what will happen if you do that.<P><A NAME="IDX192"></A><H3><A NAME="SEC40" HREF="library_toc.html#SEC40" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC40">Extra Fast Growing Objects</A></H3><P>The usual functions for growing objects incur overhead for checkingwhether there is room for the new growth in the current chunk.  If youare frequently constructing objects in small steps of growth, thisoverhead can be significant.<P>You can reduce the overhead by using special "fast growth"functions that grow the object without checking.  In order to have arobust program, you must do the checking yourself.  If you do this checkingin the simplest way each time you are about to add data to the object, youhave not saved anything, because that is what the ordinary growthfunctions do.  But if you can arrange to check less often, or checkmore efficiently, then you make the program faster.<P>The function <CODE>obstack_room</CODE> returns the amount of room availablein the current chunk.  It is declared as follows:<P><A NAME="IDX193"></A><U>Function:</U> size_t <B>obstack_room</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>)</I><P>This returns the number of bytes that can be added safely to the currentgrowing object (or to an object about to be started) in obstack<VAR>obstack</VAR> using the fast growth functions.<P>While you know there is room, you can use these fast growth functionsfor adding data to a growing object:<P><A NAME="IDX194"></A><U>Function:</U> void <B>obstack_1grow_fast</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>, char <VAR>c</VAR>)</I><P>The function <CODE>obstack_1grow_fast</CODE> adds one byte containing thecharacter <VAR>c</VAR> to the growing object in obstack <VAR>obstack_ptr</VAR>.<P><A NAME="IDX195"></A><U>Function:</U> void <B>obstack_blank_fast</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>, size_t <VAR>size</VAR>)</I><P>The function <CODE>obstack_blank_fast</CODE> adds <VAR>size</VAR> bytes to thegrowing object in obstack <VAR>obstack_ptr</VAR> without initializing them.<P>When you check for space using <CODE>obstack_room</CODE> and there is notenough room for what you want to add, the fast growth functionsare not safe.  In this case, simply use the corresponding ordinarygrowth function instead.  Very soon this will copy the object to anew chunk; then there will be lots of room available again. <P>So, each time you use an ordinary growth function, check afterward forsufficient space using <CODE>obstack_room</CODE>.  Once the object is copiedto a new chunk, there will be plenty of space again, so the program willstart using the fast growth functions again.<P>Here is an example:<P><PRE>voidadd_string (struct obstack *obstack, char *ptr, size_t len){  while (len &#62; 0)    {      if (obstack_room (obstack) &#62; len)        {          /* We have enough room: add everything fast.  */          while (len-- &#62; 0)            obstack_1grow_fast (obstack, *ptr++);        }      else        {          /* Not enough room. Add one character slowly,             which may copy to a new chunk and make room.  */          obstack_1grow (obstack, *ptr++);          len--;        }    }}</PRE><P><A NAME="IDX196"></A><A NAME="IDX197"></A><H3><A NAME="SEC41" HREF="library_toc.html#SEC41" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC41">Status of an Obstack</A></H3><P>Here are functions that provide information on the current status ofallocation in an obstack.  You can use them to learn about an object whilestill growing it.<P><A NAME="IDX198"></A><U>Function:</U> void * <B>obstack_base</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>)</I><P>This function returns the tentative address of the beginning of thecurrently growing object in <VAR>obstack_ptr</VAR>.  If you finish the objectimmediately, it will have that address.  If you make it larger first, itmay outgrow the current chunk--then its address will change!<P>If no object is growing, this value says where the next object youallocate will start (once again assuming it fits in the currentchunk).<P><A NAME="IDX199"></A><U>Function:</U> void * <B>obstack_next_free</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>)</I><P>This function returns the address of the first free byte in the currentchunk of obstack <VAR>obstack_ptr</VAR>.  This is the end of the currentlygrowing object.  If no object is growing, <CODE>obstack_next_free</CODE>returns the same value as <CODE>obstack_base</CODE>.<P><A NAME="IDX200"></A><U>Function:</U> size_t <B>obstack_object_size</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>)</I><P>This function returns the size in bytes of the currently growing object.This is equivalent to<P><PRE>obstack_next_free (<VAR>obstack_ptr</VAR>) - obstack_base (<VAR>obstack_ptr</VAR>)</PRE><P><A NAME="IDX201"></A><H3><A NAME="SEC42" HREF="library_toc.html#SEC42" tppabs="http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_toc.html#SEC42">Alignment of Data in Obstacks</A></H3><P>Each obstack has an <DFN>alignment boundary</DFN>; each object allocated inthe obstack automatically starts on an address that is a multiple of thespecified boundary.  By default, this boundary is 4 bytes.<P>To access an obstack's alignment boundary, use the macro<CODE>obstack_alignment_mask</CODE>, whose function prototype looks likethis:<P><A NAME="IDX202"></A><U>Macro:</U> int <B>obstack_alignment_mask</B> <I>(struct obstack *<VAR>obstack_ptr</VAR>)</I><P>The value is a bit mask; a bit that is 1 indicates that the correspondingbit in the address of an object should be 0.  The mask value should be oneless than a power of 2; the effect is that all object addresses aremultiples of that power of 2.  The default value of the mask is 3, so thataddresses are multiples of 4.  A mask value of 0 means an object can starton any multiple of 1 (that is, no alignment is required).<P>The expansion of the macro <CODE>obstack_alignment_mask</CODE> is an lvalue,so you can alter the mask by assignment.  For example, this statement:<P><PRE>obstack_alignment_mask (obstack_ptr) = 0;</PRE><P>has the effect of turning off alignment processing in the specified obstack.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -