home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / C / CTUTOR1.ZIP / CHAP12.TXT < prev    next >
Encoding:
Text File  |  1986-06-30  |  26.4 KB  |  587 lines

  1.                       Chapter 12 - Dynamic Allocation
  2.  
  3.  
  4.                         WHAT IS DYNAMIC ALLOCATION?
  5.  
  6.              Dynamic allocation is very intimidating to a person the 
  7.  
  8.         first time he comes across it, but that need not be.  Simply 
  9.  
  10.         relax  and  read this chapter carefully and you will have  a 
  11.  
  12.         good grounding in a very valuable programming resource.  All 
  13.  
  14.         of the variables in every program up to this point have been 
  15.  
  16.         static  variables as far as we  are  concerned.   (Actually, 
  17.  
  18.         some  of  them  have been "automatic" and  were  dynamically 
  19.  
  20.         allocated for you by the system,  but it was transparent  to 
  21.  
  22.         you.)   In  this  chapter,  we will study  some  dynamically 
  23.  
  24.         allocated variables.   They are simply variables that do not 
  25.  
  26.         exist   when  the  program  is  loaded,   but  are   created 
  27.  
  28.         dynamically as they are needed.  It is possible, using these 
  29.  
  30.         techniques, to create as many variables as needed, use them, 
  31.  
  32.         and deallocate their space for use by other  variables.   As 
  33.  
  34.         usual,  the best teacher is an example,  so load and display 
  35.  
  36.         the program named DYNLIST.C.
  37.  
  38.              We  begin by defining a named structure "animal" with a 
  39.  
  40.         few  fields  pertaining  to dogs.   We  do  not  define  any 
  41.  
  42.         variables of this type,  only three pointers.  If you search 
  43.  
  44.         through  the  remainder  of the program,  you will  find  no 
  45.  
  46.         variables defined so we have nothing to store data in.   All 
  47.  
  48.         we have to work with are three pointers, each of which point 
  49.  
  50.         to the defined structure.   In order to do anything, we need 
  51.  
  52.         some variables, so we will create some dynamically.
  53.  
  54.                          DYNAMIC VARIABLE CREATION
  55.  
  56.              The first program statement, which assigns something to 
  57.  
  58.         the   pointer  "pet1"  will  create  a   dynamic   structure 
  59.  
  60.         containing  three variables.   The heart of the statement is 
  61.  
  62.         the "malloc" function buried in the middle of the statement.  
  63.  
  64.         This  is a "memory allocate" function that needs  the  other 
  65.  
  66.         things to completely define it.   The "malloc" function,  by 
  67.  
  68.         default, will allocate a piece of memory on a "heap" that is 
  69.  
  70.         "n" characters in length and will be of type character.  The 
  71.  
  72.         "n"  must be specified as the only argument to the function.  
  73.  
  74.         We will discuss "n" shortly,  but first we need to define  a 
  75.  
  76.         "heap".
  77.  
  78.                               WHAT IS A HEAP?
  79.  
  80.              Every compiler has a set of limitations on it as to how 
  81.  
  82.         big  the executable file can be,  how many variables can  be 
  83.  
  84.         used,  how long the source file can be, etc.  One limitation 
  85.  
  86.         placed  on  users  by  many compilers  for  the  IBM-PC  and 
  87.  
  88.         compatibles is a limit of 64K for the executable code.  This 
  89.  
  90.         is  because  the  IBM-PC uses a microprocessor  with  a  64K 
  91.  
  92.         segment  size,  and  it requires special calls to  use  data 
  93.  
  94.  
  95.  
  96.                                   Page 83
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.                       Chapter 12 - Dynamic Allocation
  107.  
  108.  
  109.         outside  of a single segment.   In order to keep the program 
  110.  
  111.         small  and  efficient,  these calls are not  used,  and  the 
  112.  
  113.         program is limited but still adequate for most programs. 
  114.  
  115.              A  heap is an area outside of this 64K  boundary  which 
  116.  
  117.         can  be accessed by the program to store data and variables.  
  118.  
  119.         The  data and variables are put on the "heap" by the  system 
  120.  
  121.         as  calls to "malloc" are made.   The system keeps track  of 
  122.  
  123.         where  the  data  is stored.   Data  and  variables  can  be 
  124.  
  125.         deallocated  as desired leading to holes in the  heap.   The 
  126.  
  127.         system  knows  where  the holes are and will  use  them  for 
  128.  
  129.         additional  data  storage as more "malloc" calls  are  made.  
  130.  
  131.         The  structure  of  the  heap is therefore  a  very  dynamic 
  132.  
  133.         entity, changing constantly.
  134.  
  135.                             MORE ABOUT SEGMENTS
  136.  
  137.              Some  of the more expensive compilers give the  user  a 
  138.  
  139.         choice  of memory models to use.   Examples are Lattice  and 
  140.  
  141.         Microsoft,  which  allow the programmer a choice of using  a 
  142.  
  143.         model  with  a  64K  limitation on  program  size  but  more 
  144.  
  145.         efficient  running,  or using a model with a 640K limitation 
  146.  
  147.         and requiring longer address calls leading to less efficient 
  148.  
  149.         addressing.   Using the larger address space requires  inter 
  150.  
  151.         segment  addressing resulting in the slightly slower running 
  152.  
  153.         time.   The time is probably insignificant in most programs, 
  154.  
  155.         but there are other considerations.
  156.  
  157.              If  a program uses no more than 64K bytes for the total 
  158.  
  159.         of its code and memory and if it doesn't use a stack, it can 
  160.  
  161.         be made into a .COM file.  Since a .COM file is already in a 
  162.  
  163.         memory image format, it can be loaded very quickly whereas a 
  164.  
  165.         file  in a .EXE format must have its addresses relocated  as 
  166.  
  167.         it is loaded.  Therefore a small memory model can generate a 
  168.  
  169.         program  that loads faster than one generated with a  larger 
  170.  
  171.         memory model.   Don't let this worry you, it is a fine point 
  172.  
  173.         that few programmers worry about.
  174.  
  175.              Using dynamic allocation,  it is possible to store  the 
  176.  
  177.         data  on  the "heap" and that may be enough to allow you  to 
  178.  
  179.         use the small memory model.   Of course,  you wouldn't store 
  180.  
  181.         local  variables such as counters and indexes on  the  heap, 
  182.  
  183.         only very large arrays or structures. 
  184.  
  185.              Even  more  important than the need to stay within  the 
  186.  
  187.         small memory model is the need to stay within the  computer.  
  188.  
  189.         If  you  had a program that used several large data  storage 
  190.  
  191.         areas,  but not at the same time,  you could load one  block 
  192.  
  193.         storing  it  dynamically,  then get rid of it and reuse  the 
  194.  
  195.         space for the next large block of data.  Dynamically storing 
  196.  
  197.         each block of data in succession, and using the same storage 
  198.  
  199.  
  200.  
  201.                                   Page 84
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.                       Chapter 12 - Dynamic Allocation
  212.  
  213.  
  214.         for  each block may allow you to run your entire program  in 
  215.  
  216.         the computer without breaking it up into smaller programs. 
  217.  
  218.                        BACK TO THE "MALLOC" FUNCTION
  219.  
  220.              Hopefully  the above description of the "heap" and  the 
  221.  
  222.         overall plan for dynamic allocation helped you to understand 
  223.  
  224.         what  we are doing with the "malloc"  function.   It  simply 
  225.  
  226.         asks the system for a block of memory of the size specified, 
  227.  
  228.         and  gets  the block with the pointer pointing to the  first 
  229.  
  230.         element of the block.   The only argument in the parentheses 
  231.  
  232.         is the size of the block desired and in our present case, we 
  233.  
  234.         desire  a  block  that will hold one of  the  structures  we 
  235.  
  236.         defined at the beginning of the program.   The "sizeof" is a 
  237.  
  238.         new function,  new to us at least,  that returns the size in 
  239.  
  240.         bytes of the argument within its parentheses.  It therefore, 
  241.  
  242.         returns  the size of the structure named animal,  in  bytes, 
  243.  
  244.         and  that  number is sent to the system  with  the  "malloc" 
  245.  
  246.         call.   At  the completion of that call,  we have a block on 
  247.  
  248.         the  heap allocated to us,  with pet1 pointing to the  first 
  249.  
  250.         byte of the block.     
  251.  
  252.                               WHAT IS A CAST?
  253.  
  254.              We  still  have  a  funny  looking  construct  at   the 
  255.  
  256.         beginning  of the "malloc" function call.   That is called a 
  257.  
  258.         "cast".   The  "malloc"  function returns a block  with  the 
  259.  
  260.         pointer  pointing  to it being a pointer of type  "char"  by 
  261.  
  262.         default.  Many times, if not most, you do not want a pointer 
  263.  
  264.         to a "char" type variable,  but to some other type.  You can 
  265.  
  266.         define  the  pointer type with the construct  given  on  the 
  267.  
  268.         example line.   In this case we want the pointer to point to 
  269.  
  270.         a  structure of type "animal",  so we tell the compiler with 
  271.  
  272.         this strange looking construct.   Even if you omit the cast, 
  273.  
  274.         most compilers will return a pointer correctly,  give you  a 
  275.  
  276.         warning,  and  go  on to produce a working program.   It  is 
  277.  
  278.         better programming practice to provide the compiler with the 
  279.  
  280.         cast to prevent getting the warning message.
  281.  
  282.                 USING THE DYNAMICALLY ALLOCATED MEMORY BLOCK
  283.  
  284.              If you remember our studies of structures and pointers, 
  285.  
  286.         you  will recall that if we have a structure with a  pointer 
  287.  
  288.         pointing  to it,  we can access any of the variables  within 
  289.  
  290.         the structure.   In the next three lines of the program,  we 
  291.  
  292.         assign  some silly data to the structure  for  illustration.  
  293.  
  294.         It  should come as no surprise to you that these  assignment 
  295.  
  296.         statements  look just like assignments to statically defined 
  297.  
  298.         variables.
  299.  
  300.  
  301.  
  302.  
  303.  
  304.                                   Page 85
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.                       Chapter 12 - Dynamic Allocation
  315.  
  316.  
  317.              In the next statement, we assign the value of "pet1" to 
  318.  
  319.         "pet2" also.   This creates no new data,  we simply have two 
  320.  
  321.         pointers  to the same object.   Since "pet2" is pointing  to 
  322.  
  323.         the structure we created above,  "pet1" can be reused to get 
  324.  
  325.         another  dynamically allocated structure which is just  what 
  326.  
  327.         we  do next.   Keep in mind that "pet2" could have  just  as 
  328.  
  329.         easily been used for the new allocation.   The new structure 
  330.  
  331.         is filled with silly data for illustration.
  332.  
  333.              Finally,  we  allocate another block on the heap  using 
  334.  
  335.         the  pointer  "pet3",  and fill its block with  illustrative 
  336.  
  337.         data.
  338.  
  339.              Printing  the  data out should pose no problem  to  you 
  340.  
  341.         since  there is nothing new in the three  print  statements.  
  342.  
  343.         It is left for you to study.
  344.  
  345.                GETTING RID OF THE DYNAMICALLY ALLOCATED DATA
  346.  
  347.              Another new function is used to get rid of the data and 
  348.  
  349.         free  up  the  space on the heap  for  reuse,  the  function 
  350.  
  351.         "free".   To use it,  you simply call it with the pointer to 
  352.  
  353.         the   block  as  the  only  argument,   and  the  block   is 
  354.  
  355.         deallocated.
  356.  
  357.              In  order  to illustrate another aspect of the  dynamic 
  358.  
  359.         allocation and deallocation of data,  an additional step  is 
  360.  
  361.         included in the program on your monitor.  The pointer "pet1" 
  362.  
  363.         is assigned the value of "pet3".   In doing this,  the block 
  364.  
  365.         that  "pet1" was pointing to is effectively lost since there 
  366.  
  367.         is  no pointer that is now pointing to that block.   It  can 
  368.  
  369.         therefore never again be referred to,  changed,  or disposed 
  370.  
  371.         of.   That memory,  which is a block on the heap,  is wasted 
  372.  
  373.         from  this point on.   This is not something that you  would 
  374.  
  375.         ever  purposely do in a program.   It is only done here  for 
  376.  
  377.         illustration.
  378.  
  379.              The  first  "free" function call removes the  block  of 
  380.  
  381.         data that "pet1" and "pet3" were pointing to, and the second 
  382.  
  383.         "free"  call  removes  the block of  data  that  "pet2"  was 
  384.  
  385.         pointing  to.   We therefore have lost access to all of  our 
  386.  
  387.         data  generated earlier.   There is still one block of  data 
  388.  
  389.         that  is on the heap but there is no pointer to it since  we 
  390.  
  391.         lost  the address to it.   Trying to "free" the data pointed 
  392.  
  393.         to by "pet1" would result in an error because it has already 
  394.  
  395.         been  "freed"  by the use of "pet3".   There is no  need  to 
  396.  
  397.         worry,  when  we  return to DOS,  the entire  heap  will  be 
  398.  
  399.         disposed  of with no regard to what we have put on it.   The 
  400.  
  401.         point  does need to made that losing a pointer to a block of 
  402.  
  403.         the  heap,  forever removes that block of data storage  from 
  404.  
  405.         our program and we may need that storage later.
  406.  
  407.  
  408.  
  409.                                   Page 86
  410.  
  411.  
  412.  
  413.  
  414.  
  415.  
  416.  
  417.  
  418.  
  419.                       Chapter 12 - Dynamic Allocation
  420.  
  421.  
  422.  
  423.              Compile and run the program to see if it does what  you 
  424.  
  425.         think it should do based on this discussion.
  426.  
  427.                         THAT WAS A LOT OF DISCUSSION
  428.  
  429.              It took nearly four pages to get through the discussion 
  430.  
  431.         of  the last program but it was time well spent.   It should 
  432.  
  433.         be  somewhat exciting to you to know that there  is  nothing 
  434.  
  435.         else to learn about dynamic allocation,  the last four pages 
  436.  
  437.         covered  it all.   Of course,  there is a lot to learn about 
  438.  
  439.         the  technique  of using dynamic allocation,  and  for  that 
  440.  
  441.         reason,  there  are two more files to study.   But the  fact 
  442.  
  443.         remains,  there  is  nothing  more to  learn  about  dynamic 
  444.  
  445.         allocation than what was given so far in this chapter.
  446.  
  447.                             AN ARRAY OF POINTERS
  448.  
  449.              Load and display the file BIGDYNL.C for another example 
  450.  
  451.         of dynamic allocation.   This program is very similar to the 
  452.  
  453.         last one since we use the same structure,  but this time  we 
  454.  
  455.         define an array of pointers to illustrate the means by which 
  456.  
  457.         you  could build a large database using an array of pointers 
  458.  
  459.         rather  than a single pointer to each element.   To keep  it 
  460.  
  461.         simple  we  define  12 elements in  the  array  and  another 
  462.  
  463.         working pointer named "point".
  464.  
  465.              The "*pet[12]" is new to you so a few words would be in 
  466.  
  467.         order.  What we have defined is an array of 12 pointers, the 
  468.  
  469.         first  being "pet[0]",  and the last  "pet[11]".   Actually, 
  470.  
  471.         since an array is itself a pointer, the name "pet" by itself 
  472.  
  473.         is a pointer to a pointer.   This is valid in C, and in fact 
  474.  
  475.         you  can  go  farther  if needed but you  will  get  quickly 
  476.  
  477.         confused.   I  know  of no limit as to how  many  levels  of 
  478.  
  479.         pointing are possible,  so a definition such as "int ****pt" 
  480.  
  481.         is legal as a pointer to a pointer to a pointer to a pointer 
  482.  
  483.         to an integer type variable, if I counted right.  Such usage 
  484.  
  485.         is discouraged until you gain considerable experience.
  486.  
  487.              Now that we have 12 pointers which can be used like any 
  488.  
  489.         other  pointer,  it  is a simple matter to write a  loop  to 
  490.  
  491.         allocate  a data block dynamically for each and to fill  the 
  492.  
  493.         respective  fields with any data desirable.   In this  case, 
  494.  
  495.         the  fields  are  filled with simple data  for  illustrative 
  496.  
  497.         purposes,  but we could be reading in a  database,  readings 
  498.  
  499.         from some test equipment, or any other source of data.
  500.  
  501.              A  few fields are randomly picked to receive other data 
  502.  
  503.         to illustrate that simple assignments can be used,  and  the 
  504.  
  505.         data is printed out to the monitor.   The pointer "point" is 
  506.  
  507.         used  in the printout loop only to serve as an illustration, 
  508.  
  509.  
  510.  
  511.                                   Page 87
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.                       Chapter 12 - Dynamic Allocation
  522.  
  523.  
  524.         the  data could have been easily printed using the  "pet[n]" 
  525.  
  526.         means  of definition.   Finally,  all 12 blocks of data  are 
  527.  
  528.         freed before terminating the program.
  529.  
  530.              Compile  and run this program to aid  in  understanding 
  531.  
  532.         this  technique.   As stated earlier,  there was nothing new 
  533.  
  534.         here  about  dynamic  allocation,  only about  an  array  of 
  535.  
  536.         pointers.
  537.  
  538.                                A LINKED LIST
  539.  
  540.              We  finally  come to the grandaddy of  all  programming 
  541.  
  542.         techniques as far as being intimidating.   Load the  program 
  543.  
  544.         DYNLINK.C  for an example of a dynamically allocated  linked 
  545.  
  546.         list.   It  sounds terrible,  but after a little time  spent 
  547.  
  548.         with it,  you will see that it is simply another programming 
  549.  
  550.         technique  made  up  of  simple components  that  can  be  a 
  551.  
  552.         powerful tool.
  553.  
  554.              In order to set your mind at ease,  consider the linked 
  555.  
  556.         list  you used when you were a child.   Your sister gave you 
  557.  
  558.         your birthday present,  and when you opened it,  you found a 
  559.  
  560.         note that said,  "Look in the hall closet."  You went to the 
  561.  
  562.         hall closet,  and found another note that said, "Look behind 
  563.  
  564.         the  TV  set."  Behind the TV you found  another  note  that 
  565.  
  566.         said,  "Look  under  the  coffee pot."  You  continued  this 
  567.  
  568.         search,  and finally you found your pair of socks under  the 
  569.  
  570.         dogs  feeding dish.   What you actually did was to execute a 
  571.  
  572.         linked  list,  the starting point being the wrapped  present 
  573.  
  574.         and the ending point being under the dogs feeding dish.  The 
  575.  
  576.         list ended at the dogs feeding dish since there were no more 
  577.  
  578.         notes.
  579.  
  580.              In  the program DYNLINK.C,  we will be doing  the  same 
  581.  
  582.         thing as your sister forced you to do.   We will however, do 
  583.  
  584.         it  much  faster and we will leave a little pile of data  at 
  585.  
  586.         each of the intermediate points along the way.  We will also 
  587.  
  588.         have   the  capability  to  return  to  the  beginning   and 
  589.  
  590.         retraverse the entire list again and again if we so desire.
  591.  
  592.                             THE DATA DEFINITIONS
  593.  
  594.              This program starts similarly to the last two with  the 
  595.  
  596.         addition  of the definition of a constant to be used  later.  
  597.  
  598.         The  structure  is nearly the same as that used in the  last 
  599.  
  600.         two programs except for the addition of another field within 
  601.  
  602.         the structure,  the pointer.   This pointer is a pointer  to 
  603.  
  604.         another  structure  of  this same type and will be  used  to 
  605.  
  606.         point to the next structure in order.  To continue the above 
  607.  
  608.         analogy,  this pointer will point to the next note, which in 
  609.  
  610.         turn will contain a pointer to the next note after that.
  611.  
  612.  
  613.  
  614.                                   Page 88
  615.  
  616.  
  617.  
  618.  
  619.  
  620.  
  621.  
  622.  
  623.  
  624.                       Chapter 12 - Dynamic Allocation
  625.  
  626.  
  627.  
  628.              We  define three pointers to this structure for use  in 
  629.  
  630.         the program, and one integer to be used as a counter, and we 
  631.  
  632.         are ready to begin using the defined structure for  whatever 
  633.  
  634.         purpose  we  desire.   In  this case,  we  will  once  again 
  635.  
  636.         generate nonsense data for illustrative purposes.
  637.  
  638.                               THE FIRST FIELD
  639.  
  640.              Using  the  "malloc" function,  we request a  block  of 
  641.  
  642.         storage on the "heap" and fill it with data.  The additional  
  643.  
  644.         field in this example, the pointer, is assigned the value of 
  645.  
  646.         NULL, which is only used to indicate that this is the end of 
  647.  
  648.         the  list.   We  will  leave  the pointer  "start"  at  this 
  649.  
  650.         structure,  so  that  it  will always  point  to  the  first 
  651.  
  652.         structure of the list.   We also assign "prior" the value of 
  653.  
  654.         "start" for reasons we will see soon.  Keep in mind that the 
  655.  
  656.         end  points of a linked list will always have to be  handled 
  657.  
  658.         differently  than those in the middle of a list.   We have a 
  659.  
  660.         single  element  of  our  list now and  it  is  filled  with 
  661.  
  662.         representative data.
  663.  
  664.                        FILLING ADDITIONAL STRUCTURES
  665.  
  666.              The  next group of assignments and  control  statements 
  667.  
  668.         are  included  within a "for" loop so we can build our  list 
  669.  
  670.         fast  once  it is defined.   We will go through the  loop  a 
  671.  
  672.         number  of times equal to the constant "RECORDS" defined  at 
  673.  
  674.         the  beginning  of  our  program.   Each  time  through,  we 
  675.  
  676.         allocate memory,  fill the first three fields with nonsense, 
  677.  
  678.         and  fill the pointers.   The pointer in the last record  is 
  679.  
  680.         given  the  address of this new record because  the  "prior" 
  681.  
  682.         pointer is pointing to the prior record.  Thus "prior->next" 
  683.  
  684.         is given the address of the new record we have just  filled.  
  685.  
  686.         The  pointer in the new record is assigned the value "NULL", 
  687.  
  688.         and  the  pointer "prior" is given the address of  this  new 
  689.  
  690.         record  because the next time we create a record,  this  one 
  691.  
  692.         will  be  the  prior  one at  that  time.   That  may  sound 
  693.  
  694.         confusing  but it really does make sense if you  spend  some 
  695.  
  696.         time studying it.
  697.  
  698.              When  we have gone through the "for" loop 6  times,  we 
  699.  
  700.         will  have  a  list  of 7 structures including  the  one  we 
  701.  
  702.         generated  prior  to  the loop.   The  list  will  have  the 
  703.  
  704.         following characteristics.
  705.  
  706.  
  707.         1. "start" points to the first structure in the list.
  708.  
  709.         2. Each structure contains a pointer to the next structure.
  710.  
  711.  
  712.  
  713.  
  714.                                   Page 89
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724.                       Chapter 12 - Dynamic Allocation
  725.  
  726.  
  727.         3. The last structure has a pointer  that points to NULL and    
  728.  
  729.            can be used to detect the end.
  730.  
  731.            start->struct1              This diagram should aid in
  732.                   name              understanding the structure of
  733.                   breed             the data at this point.
  734.                   age
  735.                   point->struct2
  736.                          name
  737.                          breed
  738.                          age
  739.                          point->struct3
  740.                                 name
  741.                                 breed
  742.                                 age
  743.                                 point-> . . . . struct7
  744.                                                 name
  745.                                                 breed
  746.                                                 age
  747.                                                 point->NULL
  748.  
  749.  
  750.              It should be clear to you,  if you understand the above 
  751.  
  752.         structure,  that  it is not possible to simply jump into the 
  753.  
  754.         middle of the structure and change a few values.   The  only 
  755.  
  756.         way  to  get  to the third structure is by starting  at  the 
  757.  
  758.         beginning  and working your way down through  the  structure 
  759.  
  760.         one  record at a time.   Although this may seem like a large 
  761.  
  762.         price  to  pay for the convenience of putting so  much  data 
  763.  
  764.         outside of the program area,  it is actually a very good way 
  765.  
  766.         to store some kinds of data.
  767.  
  768.             A  word processor would be a good application  for  this 
  769.  
  770.         type  of data structure because you would never need to have 
  771.  
  772.         random access to the data.   In actual practice, this is the 
  773.  
  774.         basic type of storage used for the text in a word  processor 
  775.  
  776.         with one line of text per record.   Actually, a program with 
  777.  
  778.         any degree of sophistication would use a doubly linked list.  
  779.  
  780.         This  would  be  a list with two pointers  per  record,  one 
  781.  
  782.         pointing down to the next record,  and the other pointing up 
  783.  
  784.         to the record just prior to the one in question.  Using this 
  785.  
  786.         kind  of a record structure would allow traversing the  data 
  787.  
  788.         in either direction.
  789.  
  790.                            PRINTING THE DATA OUT
  791.  
  792.              To print the data out, a similar method is used as that 
  793.  
  794.         used to generate the data.  The pointers are initialized and 
  795.  
  796.         are  then  used  to go from record  to  record  reading  and 
  797.  
  798.         displaying   each  record  one  at  a  time.    Printing  is 
  799.  
  800.         terminated when the NULL on the last record is found, so the 
  801.  
  802.  
  803.  
  804.                                   Page 90
  805.  
  806.  
  807.  
  808.  
  809.  
  810.  
  811.  
  812.  
  813.  
  814.                       Chapter 12 - Dynamic Allocation
  815.  
  816.  
  817.         program  doesn't even need to know how many records  are  in 
  818.  
  819.         the list.   Finally, the entire list is deleted to make room 
  820.  
  821.         in  memory  for any additional data that may be  needed,  in 
  822.  
  823.         this case, none.  Care must be taken to assure that the last 
  824.  
  825.         record is not deleted before the NULL is checked.   Once the 
  826.  
  827.         data is gone,  it is impossible to know if you are  finished 
  828.  
  829.         yet.
  830.  
  831.                MORE ABOUT DYNAMIC ALLOCATION AND LINKED LISTS
  832.  
  833.              It  is  not difficult,  and it is not trivial,  to  add 
  834.  
  835.         elements into the middle of a linked lists.  It is necessary 
  836.  
  837.         to create the new record,  fill it with data,  and point its 
  838.  
  839.         pointer to the record it is desired to precede.   If the new 
  840.  
  841.         record  is  to be installed between the  3rd  and  4th,  for 
  842.  
  843.         example,  it is necessary for the new record to point to the 
  844.  
  845.         4th record,  and the pointer in the 3rd record must point to 
  846.  
  847.         the new one.  Adding a new record to the beginning or end of 
  848.  
  849.         a  list are each special cases.   Consider what must be done 
  850.  
  851.         to add a new record in a doubly linked list. 
  852.  
  853.              Entire books are written describing different types  of 
  854.  
  855.         linked lists and how to use them,  so no further detail will 
  856.  
  857.         be  given.   The amount of detail given should be sufficient 
  858.  
  859.         for a beginning understanding of C and its capabilities.
  860.  
  861.                        ANOTHER NEW FUNCTION - CALLOC
  862.  
  863.              One  more  function must  be  mentioned,  the  "calloc" 
  864.  
  865.         function.   This  function  allocates a block of memory  and 
  866.  
  867.         clears  it  to  all  zeros  which  may  be  useful  in  some 
  868.  
  869.         circumstances.   It is similar to "malloc" and will be  left 
  870.  
  871.         as an exercise for you to read about and use "calloc" if you 
  872.  
  873.         desire.
  874.  
  875.         PROGRAMMING EXERCISES
  876.  
  877.         1.  Rewrite the example program STRUCT1.C from chapter 11 to 
  878.  
  879.             dynamically allocate the two structures.
  880.  
  881.         2.  Rewrite the example program STRUCT2.C from chapter 11 to 
  882.  
  883.             dynamically allocate the 12 structures.
  884.  
  885.  
  886.  
  887.  
  888.  
  889.  
  890.  
  891.  
  892.  
  893.  
  894.  
  895.                                   Page 91
  896.  
  897.