Computer Science 210 Computer Organization Pointers and Dynamic Storage
Heap Allocation and Deallocation The C programmer must run functions to allocate and deallocate memory for dynamic storage (referenced by pointers) malloc allocates a block of storage from the heap free returns storage to the heap
Declare a Pointer to an int int *intPtr; The variable is uninitialized and contains garbage, but it can point to an int eventually intPtr
Declare and Initialize to NULL #include <stdio.h> int *intPtr = NULL; // NULL is the same as 0 The variable is initialized to the NULL pointer, which can now be accessed intPtr
Declare and Initialize with malloc #include <stdlib.h> int *intPtr = malloc(sizeof(int)); malloc expects an integer representing the size of the storage needed The sizeof function takes a type as an argument and returns the number of bytes needed for a value of that type malloc returns a pointer to the first byte of the storage The variable now points to a new storage area for an int, but this storage contains garbage intPtr
Access via Dereference with * #include <stdlib.h> int *intPtr = malloc(sizeof(int)); (*intPtr) = 69; printf("%d\n", *intPtr); The * operator accesses the cell pointed to The pointer must point to a cell * has a lower precedence than = The variable now points to storage that has a program-supplied value intPtr 69
Return the Storage with free #include <stdlib.h> int *intPtr = malloc(sizeof(int)); (*intPtr) = 69; printf("%d\n", *intPtr); free(intPtr); The storage is still accessible, but might be taken for other applications (also called a dangling pointer reference) The variable still points to storage, which might be used by others intPtr 69
Reset the Pointer to null #include <stdlib.h> int *intPtr = malloc(sizeof(int)); (*intPtr) = 69; printf("%d\n", *intPtr); free(intPtr); intPtr = NULL; Clean up by setting the pointer to NULL or to other storage The variable now has no dangling pointer intPtr 69
Be Careful of Memory Leaks! #include <stdlib.h> int *intPtr = malloc(sizeof(int)); (*intPtr) = 69; printf("%d\n", *intPtr); intPtr = NULL; In this case, the storage cannot be accessed by the program, or by the heap manager, and will eventually result in heap underflow! Always free your own storage! intPtr 69
Nodes and Linked Structures head data next data next size 2 Could be a linked stack How do we represent a node in C?
The C struct A struct is a data type that includes one or more named data fields Good for containing data of different types Like classes in Python or Java, but without the methods
Declare a Type and Two Variables struct point{ int x, y; } p1, p2; p1 x Storage is automatically allocated when variables are declared y p2 x y
Initialize the Fields of p1 struct point{ int x, y; } p1, p2; p1.x = 44; p1.y = 55; p1 44 x The field selector (.) accesses a field for reference or assignment 55 y p2 x y
Copy p1 to p2 struct point{ int x, y; } p1, p2; p1.x = 44; p1.y = 55; p2 = p1; p1 44 x Unlike arrays, the contents of an entire struct can be assigned to another one 55 y p2 44 x 55 y
Variation Can declare the type, then the variables later struct point{ int x, y; }; struct point p1, p2; p1.x = 44; p1.y = 55; p2 = p1; p1 44 x Can declare the type, then the variables later 55 y p2 44 x 55 y
Create a Synonym with typedef typedef struct point{ int x, y; } point_t; point_t p1, p2; p1.x = 44; p1.y = 55; p2 = p1; p1 44 x This synonym happens to be the same name as the name of the struct 55 y p2 44 x 55 y
Declare a Node Type typedef struct node{ int data; struct node *next; } node; typedef node* nodePtr; No storage yet, because no variables have been declared
Declare a Pointer Variable to a Node typedef struct node{ int data; struct node *next; } node; typedef node* nodePtr; nodePtr ptr; ptr ptr contains garbage
Initialize It to a New Node typedef struct node{ int data; struct node *next; } node; typedef node* nodePtr; nodePtr ptr = malloc(sizeof(node)); ptr malloc allocates storage for the entire node
Initialize the Node’s Contents typedef struct node{ int data; struct node *next; } node; typedef node* nodePtr; nodePtr ptr = malloc(sizeof(node)); ptr->data = 69; ptr->next = NULL; ptr 69 The -> operator combines * (dereference) and . (field selection)
Define a Helper Function getNode typedef struct node{ int data; struct node *next; } node; typedef node* nodePtr; nodePtr getNode(int data, nodePtr next){; nodePtr ptr = malloc(sizeof(node)); ptr->data = data; ptr->next = next; return ptr; } This function creates a new node, initializes its contents, and returns a pointer to it
Create a Linked Structure! typedef struct node{ int data; struct node *next; } node; typedef node* nodePtr; nodePtr getNode(int data, nodePtr next){; nodePtr ptr = malloc(sizeof(node)); ptr->data = data; ptr->next = next; return ptr; } int i; nodePtr head = NULL; for (i = 1; i <= 3; i++) head = getNode(i, head); head 3 2 1
The Header File for a Linked Stack typedef struct node{ int data; struct node *next; } node; typedef node* nodePtr; typedef struct linkedStack{ int size; nodePtr top; } linkedStack; linkedStack newStack(); void push(linkedStack *stk, int data); int pop(linkedStack *stk); int size(linkedStack stk);
The Implementation linkedStack newStack(){ linkedStack stk; stk.top = NULL; stk.size = 0; return stk; } void push(linkedStack *stk, int data){ stk->top = getNode(data, stk->top); stk->size = stk->size + 1; int pop(linkedStack *stk){ int data = stk->top->data; nodePtr garbage = stk->top; stk->top = stk->top->next; free(garbage); stk->size = stk->size - 1; return data; int size(linkedStack stk){ return stk.size;
Using the Linked Stack #include <stdio.h> #include "stack.h" int main(){ linkedStack stk = newStack(); int i; for (i = 1; i <= 5; i++) push(&stk, i); printf("The stack has %d elements\n", size(stk)); while (size(stk) > 0) printf("Popping %d\n", pop(&stk)); }
Developing an Assembler in C For Wednesday Developing an Assembler in C