Topic 12 - PowerPoint PPT Presentation

1 / 54
About This Presentation
Title:

Topic 12

Description:

Thus, malloc and free can be thought of as companion functions. ... Notice in the picture that the last node in the list had its link pointer set to ... – PowerPoint PPT presentation

Number of Views:34
Avg rating:3.0/5.0
Slides: 55
Provided by: jeffre78
Category:
Tags: topic

less

Transcript and Presenter's Notes

Title: Topic 12


1
Topic 12 Dynamic Memory Allocation Linked
Lists
2
Static Memory Allocation
  • So far, we have only seen static memory
    allocation.
  • This means that the number of variables a program
    will use, and their sizes, are fixed and known
    when the program is written and compiled.
  • It is possible to read through a program and
    calculate exactly how much memory will be
    required when the program is run, and how much
    memory each variable and/or data structure will
    need.

3
Static Memory Allocation
  • Notice that this requires that the maximum number
    of elements in an array must be known when the
    program is written.
  • This is not practical, as the total number of
    variables may not be known in advance.
  • For example, in writing a student record database
    program, the number of students may not be known
    in advance. This may result in far too much
    memory being allocated or not enough.

4
Static Memory Allocation
  • It is clear why the approach we have seen thus
    far is limited.
  • We need to know how many variables the program
    will need in advance.
  • If this number is too low, the program will not
    be able to handle the necessary data.
  • If this number is too high, the program will
    waste memory, as all of the allocated memory will
    not be used.

5
Dynamic Memory Allocation
  • These disadvantages are overcome by making use of
    dynamic memory allocation.
  • This refers to a program deciding at run-time how
    much memory to allocate.
  • A program can call certain functions to allocate
    memory at any time. Therefore, the program can
    use input data as the basis for determining how
    much space to request and what type of data to
    store in this space.

6
Dynamic Memory Allocation
  • As dynamic memory allocation allows the program
    to make direct use of memory, it is clear that
    pointers must be used in some fashion.
  • Using dynamic data structures requires the
    sophisticated use of pointers thus we will
    briefly summarize the use of pointers we have
    covered thus far.

7
A Quick Review of Pointers
  • A pointer is a variable that holds a memory
    address.
  • We can use the operator to dereference a
    pointer. This refers to following the pointer
    to get what it is pointing to.
  • We can pass pointers to (the addresses of)
    variables into functions this allows the
    function to modify variables local to the calling
    function (call-by-reference). This allows the
    use of function output parameters.

8
A Quick Review of Pointers
  • The name of an array is simply the address of the
    first element of that array. Thus, we can think
    of an array name as a pointer to the array.
  • A string is simply an array of characters, thus
    it behaves just like an array.
  • As arrays are simply pointers to their first
    elements, anytime we pass an array (or string)
    into a function, this call is call-by-reference.
    The function can modify the array.

9
Something NewKind of.Null Pointers
  • A pointer is a memory address.
  • Any pointer can have a special value, NULL. This
    value means does not point to anything.
  • If a pointer is set to NULL, it cannot be
    dereferenced. Any attempt to do so will cause a
    segmentation fault.
  • A pointer is set to NULL using the standard
    assignment statement syntax

int num1_p num1_p NULL
10
Null Pointers
  • We can also test to see if a pointer is set to
    NULL, using standard comparisons.
  • if (num1_p NULL)
  • / points to nothing /
  • else
  • / points to something /
  • Why this is an important concept will become
    clear later. Null pointers are used extensively
    to mark the end of dynamic data structures, such
    as linked lists.

11
A Quick Review of Pointers
  • When we define structures, we can also create
    pointers to variables of these user-defined
    datatypes.
  • Thus, we can see that pointers are simply memory
    addresses. They are the components of the C
    language used to manage memory.

12
The malloc Function
  • We now introduce the malloc() function. This
    function name is short for memory allocation.
  • When this function is called, the program finds
    some unallocated space in memory.
  • This function takes exactly one parameter, the
    amount of memory that the program wishes to
    allocate.
  • It returns a pointer, of type void which is the
    address where the memory that was just allocated
    begins.

13
The malloc Function
  • The one parameter passed into malloc is the size
    of the memory block we wish to allocate.
  • This size is determined using the sizeof()
    function. This function takes a datatype as a
    parameter and returns the size of the datatype
    (how much space in memory one variable of that
    datatype occupies in memory).

14
The malloc Function
  • Thus, to allocate enough space in memory to store
    an integer, we would call malloc as
  • malloc(sizeof(int))
  • Similarly, to allocate enough space in memory to
    store a student_record, we would call malloc as
  • malloc(sizeof(student_record))

15
The malloc Function
  • So, now we can allocate memory of the correct
    size to store a variablehow do we use it?
  • Remember that pointers can only point to a
    certain datatype, i.e. an int can only point to
    an integer, nothing else.
  • malloc returns a void . This is simply a memory
    address with no type.
  • Therefore, we must cast the return value of
    malloc, the address of the just-allocated memory
    block, to the type of pointer we want to store in
    that memory block.

16
The malloc Function
  • Thus, to allocate enough space in memory to store
    an integer, we would call malloc as
  • int int1_p
  • int1_p (int )malloc(sizeof(int))
  • Similarly, to allocate enough space in memory to
    store a student_record, we would call malloc as
  • student_record TopStudent_p
  • TopStudent_p
  • (student_record )malloc(sizeof(student_record))

17
The malloc Function
student_record TopStudent_p TopStudent_p
(student_record )malloc(sizeof(student_record))
  • What this call to malloc does is to allocate
    memory the size of one student_record. The
    memory address of this block of memory is stored
    in the pointer TopStudent. We cast this address
    to a student_record pointer this indicates that
    we will use this block of memory as a
    student_record datatype.

18
ReferencingDynamically Allocated Memory
  • So, now we can allocate memory dynamically and
    obtain a pointer to a specific datatype, which
    will be stored in the newly allocated memory.
  • Once this is done, values can be stored in the
    newly allocated memory using the pointer
    referencing operator , just as pointers were
    used before.

19
ReferencingDynamically Allocated Memory
int num1_p, num2_p student_record record1_p,
record2_p num1_p (int )malloc(sizeof(int))
num2_p (int )malloc(sizeof(int)) record1_p
(student_record ) malloc(sizeof(student_record))
record2_p (student_record ) malloc(sizeof(st
udent_record)) num1_p 27 num2_p
99 (record1_p).letter_grade
A strcpy(record2_p-gtlast,Six) strcpy(record2
_p-gtfirst,Jeffrey)
20
The calloc Function
  • The malloc function works well to allocate one
    variable, as we simply pass it the size of memory
    we need to allocate, which is easily obtained by
    using the sizeof function.
  • Sometimes we wish to allocate arrays dynamically.
    This can be done easily using the calloc
    function.

21
The calloc Function
  • calloc is short for contiguous allocation.
  • This function takes two parameters, the number of
    elements to allocate and the size of one element.
  • It returns a pointer to the beginning of the
    newly allocated memory block, thus this pointer
    is equal to the address of the first element of
    the array.
  • Note that this function also initializes every
    element of the new array to zero.

22
The calloc Function
  • Once an array is dynamically allocated in such a
    manner, it can be accessed using the same
    operators and other uses as a statically
    allocated array.
  • This can be shown in a simple example.

23
Dynamically AllocatingArrays with calloc
int array_of_nums char string int
size_of_string, number_of_nums printf(How
many characters in the string?) scanf(d,size
_of_string) string (char )calloc(size_of_strin
g, sizeof(char) scanf(s,string) printf(How
many numbers?) scanf(d,number_of_nums) arra
y_of_nums (int )calloc(number_of_nums,sizeof(
int)) for (count 0 count lt number_of_nums
count) scanf(d,array_of_numscount)
24
Freeing Dynamically Allocated Memory
  • Now we have seen that malloc and calloc can be
    used to dynamically allocate memory.
  • When a static variable, i.e. a local variable of
    a function, falls out of scope, for example, when
    the function it is defined in finishes (executes
    a return statement or the closing brace), C
    automatically frees that memory.
  • This means the memory used for these variables is
    deallocated (marked as free it can be used in
    the future when new memory must be allocated).

25
Freeing DynamicallyAllocated Memory
  • This is NOT true of dynamically allocated memory.
    While the pointer that we set using malloc may
    fall out of scope and be unallocated, the memory
    it points to (the memory malloc allocated) is not
    freed.
  • In C, it is the responsibility of the programmer
    to free any memory that is dynamically allocated
    in the program.

26
The free Function
  • This is done using the free function.
  • It takes one parameter, the pointer returned by
    malloc.
  • When this function is called, the memory
    allocated by malloc at the address contained in
    the pointer is deallocated (marked as free it
    can be used in the future when new memory must be
    allocated).
  • Thus, malloc and free can be thought of as
    companion functions. One allocates memory when it
    is needed, the other frees memory when it is no
    longer needed.

27
The free Function
char string int size_of_string printf(How
many characters in the string?) scanf(d,size
_of_string) string (char )calloc(size_of_strin
g, sizeof(char) scanf(s,string) printf(The
string you typed in was\ns\n,
string) free(string)
28
One Common Problem
  • One problem is quite common when using
    dynamically allocated memory.
  • Sometimes, multiple pointers can point to the
    same memory block.
  • If the free function is called with one of these
    pointers, the memory block they both point to is
    unallocated. Thus, if the second pointer (not
    the one passed to free) is later used, the memory
    it points to is no longer allocated.
  • This leads to the same problem as overstepping
    the bounds of an array (attempting to use memory
    that is not allocated).

29
One Common Problem
char string, string2 int size_of_string pri
ntf(How many characters in the
string?) scanf(d,size_of_string) string
(char )calloc(size_of_string, sizeof(char) strin
g2 string scanf(s,string) printf(The
string you typed in was\ns\n,
string) free(string) . . .
30
The Linked List
  • Now that we understand the concept of dynamic
    memory allocation, we can look at a linked list.
  • A linked list is a data structure which is a
    sequence of nodes in which each node is linked,
    or connected to, the node following it.

31
The Linked List
Data 1
Data 1
Data 2
Next node
Data 2
Data 3
Next node
Data 3
Next node
Data 4
Data 4
NO NEXT
32
The Linked List
  • In this linked list example, each node has two
    pieces of data. Each node also has a pointer to
    the next node.
  • So, we need two things to form a linked list a
    way to combine various datatypes and variables
    together into one datatype and a way to point
    to the next one of these combination datatypes.
  • Sohow can we accomplish this?

33
The Linked List
  • The first goal, combining various datatypes and
    variables into one datatype, is easily handled
    with a structure.
  • The second goal, being able to point to the
    next structure is easily handled using pointers.
  • So, we have all of the components we need in
    order to construct a linked list.

34
Structures with Pointer Components
  • We can form a linked list by defining a structure
    with a pointer component.
  • typedef struct a_node
  • char lastname20
  • float num_grade
  • struct a_node next_p
  • a_node2

35
Structureswith Pointer Components
typedef struct a_node char lastname20 float
num_grade struct a_node next_p a_node2
  • The a_node name is known as a structure tag.
    What is does is let us use the phrase struct
    a_node as an alternative to using the work
    a_node2.
  • We use this as the datatype for the link pointer,
    as the compiler has not yet reached the
    definition of the word a_node2. It has reached
    the definition of the phrase struct a_node, so we
    can use this as the datatype.

36
Structureswith Pointer Components
typedef struct char lastname20 float
num_grade a_node2 next_p a_node2
  • This definition is illegal and will result in a
    compile error. When the compiler reaches the
    declaration of the link pointer, it does not yet
    know what an a_node2 is. Thus, this will cause a
    compiler error.

37
Structureswith Pointer Components
typedef struct a_node char lastname20 float
num_grade struct a_node next_p a_node2
  • Notice that when we use this structure tag, we
    need to use the entire phrase struct a_node and
    not simply a_node.

38
Creating a Linked List
  • We can then setup a linked list using these
    structures

a_node2 node1_p, node2_p, node3_p node1_p
(a_node2 )malloc(sizeof(a_node2)) node2_p
(a_node2 )malloc(sizeof(a_node2)) node3_p
(a_node2 )malloc(sizeof(a_node2)) strcpy(node1_p
-gtlastname, Smith) strcpy(node2_p-gtlastname,
Jones) strcpy(node3_p-gtlastname,
Williams) node1_p-gtnum_grade90
node2_p-gtnum_grade20 node3_p-gtnum_grade100 nod
e1_p-gtnext_p node2_p node2_p-gtnext_p
node3_p node3_p-gtnext_p NULL
39
Creating a Linked List
Smith
Williams
Jones
90
20
100
1080
2370
NULL
Node1_p
Node3_p
Node2_p
40
Creating a Linked List
  • Notice that if we have the pointer to the first
    node in the linked list, we do not need the
    pointers to the other nodes, as the first node
    contains a pointer to the second node, the second
    node contains a pointer to the third node, etc.
  • Thus, we can access any node in the linked list
    by starting at the first node and following the
    link pointers.
  • Thus, we can think of a linked list as . . .

41
Creating a Linked List
Address 2370
Address 1080
Smith
Williams
Jones
90
20
100
1080
2370
NULL
Node1_p
42
Accessing the DataContained in a Linked List
  • So, we can see that node1_p points to the first
    node in our linked list. This first node is
    known as the head of the linked list.
  • We can access the data in the first node by using
    the -gt operator
  • printf(Names\n,node1_p-gtlastname)
  • printf(Gradef\n,node1_p-gtnum_grade)

43
Accessing the Data Contained in a Linked List
  • The first node also contains a pointer to the
    second node. Therefore, we can access this
    pointer and use it to access the data in the
    second node
  • printf(Name?)
  • scanf(s,node1_p-gtnext_p-gtlastname)
  • printf(Grade?)
  • scanf(f,(node1_p-gtnext_p-gtnum_grade))
  • printf(Names,node1_p-gtnext_p-gtlastname)
  • printf(Gradef,node1_p-gtnext_p-gtnum_grade)

44
Accessing the DataContained in a Linked List
  • We can access the data contained in nodes past
    the second node in the same manner we can simply
    follow the pointers to the next node until we
    arrive at the node that contains the data we want
    to access.
  • Thus, if the address stored in node1_p is known
    by a function, that function can access every
    element (node) of the linked list.

45
The Tail Node
  • Notice in the picture that the last node in the
    list had its link pointer set to NULL.
  • Thus, we can test to see if we are at the last
    node in a linked list.
  • If the link pointer of a node is set to NULL, we
    are at the end of the list. If the link pointer
    of a node is not set to NULL, it will point to
    the next node in the list.

46
The Tail Node
  • In this way, the NULL pointer is used to indicate
    the end of the linked list.
  • The last node in the linked list is called the
    tail of the list.
  • So, the head of the list is the first node, the
    tail of the list is the last node, and we can
    tell that we are at the tail of the list if the
    link pointer is set to NULL.

47
Linked List Advantages
  • Linked lists provide a number of advantages.
  • First and foremost, they are perfectly sized for
    the data that they store. When a data record is
    encountered, a node to store it is allocated.
    This defeats the limitations of arrays, where we
    needed to know the array size at program compile
    time.

48
Linked List Advantages
  • As linked lists are linked using pointers, it
    is easy to manipulate them.
  • Two common operations that can be easily
    performed on linked lists are the insertion of a
    node into the list (at some point) and the
    deletion of a node from the list.

49
Linked List AdvantagesInserting a Node into the
List
Address 2370
Address 1080
Smith
Williams
Jones
90
20
100
1080
2370
NULL
8460
Node1_p
2370
50
Linked List AdvantagesDeleting a Node from the
List
Address 2370
Address 1080
Smith
Williams
Jones
90
20
100
1080
2370
NULL
2370
Node1_p
51
Linked List Traversal
  • A common operation on a linked list is traversing
    a list. This means that we keep following the
    link pointers until we arrive at the end of the
    list.
  • We can write a function that traverses the linked
    list we have previously made, displaying the data
    stored in each node.

52
Linked List Traversal
void display_list(a_node2 head_p) a_node2
current_p if (head_p NULL) printf(Empty
List!) else current_p head_p while
(current_p ! NULL)
printf(s,current_p-gtlastname)
printf(d\n,current_p-gtnum_grade)
current_p current_p-gtnext_p

53
Linked List Traversal
  • We can also write a function that searches a
    linked list for a target data item, in this case,
    a last name.

54
Linked List Traversal
a_node2 serach_list(a_node2 head_p, char
target) a_node2 current_p for(current_p
head_p current_p ! NULL
strcmp(current_p-gtlastname,target) ! 0
current_p current_p-gtnext) return
current_p
Write a Comment
User Comments (0)
About PowerShow.com