<<

Pointer Overview

Lecture P8: Pointers and Linked Lists Basic memory abstraction. addr value ■ Indexed sequence of . 0 0 ■ Address = index. 1 1 2 1 Pointer = VARIABLE that stores . 3 1

Uses. 4 0 5 1 ■ Allow function to change inputs.

■ Better understanding of arrays. 6 0

■ Create "linked lists." 7 0 J ♠ Q♦ 5 ♥ NULL 8 1 9 0 10 1 ...... 256GB 1

2

Pointers in TOY Pointers in Unix % gcc pointer.c Variable that stores the value of a single MEMORY ADDRESS. C pointers. % a.out ■ In TOY, memory addresses are 00 – FF. ■ If x is an integer: x = 7 – indexed addressing: store a memory address in a register &x is a pointer to x (memory address of x) px = ffbefb24

■ Very powerful and useful programming mechanism. ■ If px is a pointer to an integer: *px = 7

■ Confusing and easy to abuse! *px is the integer pointer.c #include Address D000 D004 D008 .. D0C8 D0CC D0D0 .. D200 D204 D208 int main(void) { 9 1 D200 .. 0 7 0000 .. 5 3 D0C8 Value int x; allocate storage for int *px; pointer to int x = 7; Memory location D008 px = &x; stores a "pointer" to another printf(" x = %d\n"); memory address of interest. printf(" px = %p\n", px); printf("*px = %d\n", *px); return 0; }

3 5 Pointers as Arguments to Functions Pointers as Arguments to Functions

Goal: function that swaps values of two integers. Goal: function that swaps values of two integers.

A first attempt: badswap.c Now, one that works. swap.c #include #include changes value only swaps copies void swap(int a, int b) { stored in memory void swap(int *pa, int *pb) { of x and y int t; address for x and y int t; t = a; a = b; b = t; t = *pa; *pa = *pb; *pb = t; } }

int main(void) { int main(void) { int x = 7, y = 10; int x = 7, y = 10; swap(x, y); swap(&x, &y); printf("%d %d\n", x, y); printf("%d %d\n", x, y); return 0; return 0; } }

6 7

Linked List Overview

Goal: deal with large amounts of . addr value Fundamental data . ■ Organize data so that it is easy to manipulate. 0 0 ■ HOMOGENEOUS collection of values (all same type). ■ Time and space efficient. ■ Store values ANYWHERE in memory. 1 1 ■ Associate LINK with each value. 2 1 Basic abstraction. ■ Use link for immediate access to the NEXT value. 3 1 ■ Indexed sequence of bits. 4 0 9 5 ■ Address = index. Possible memory representation of x + 3x + 7. 5 1 ■ Assume linked list starts in location D000. Need higher level abstractions to bridge gap. 6 0 D000 D004 D008 .. D0C8 D0CC D0D0 .. D200 D204 D208 ■ Array. 7 0 Address

■ Struct. 8 1 Value 1 9 D200 .. 7 0 0000 .. 3 5 D0C8

■ LINKED LIST 9 0

■ Binary . 10 1 head 1 9 D200 7 0 0000 NULL 3 5 D0C8 ■ ...... ■ . . . 256GB 1

8 10 Linked List Linked List vs. Array

Fundamental data structure. Polynomial example illustrates basic tradeoffs.

■ HOMOGENEOUS collection of values (all same type). ■ Sparse polynomial = few terms, large exponent. 1000000 50000 ■ Store values ANYWHERE in memory. Ex. x + 5x + 7

■ ■ Associate LINK with each value. Dense polynomial = mostly nonzero coefficients. Ex. x7 + x6 + 3x4 + 2x3 + 1 ■ Use link for immediate access to the NEXT value.

Possible memory representation of x9 + 3x5 + 7. Huge Sparse Polynomial Huge Dense Polynomial

■ Assume linked list starts in location D000. array linked array linked

Address D000 D004 D008 .. D0C8 D0CC D0D0 .. D200 D204 D208 space huge tiny space huge 3 * huge Value 1 9 D200 .. 7 0 0000 .. 3 5 D0C8 time instant tiny time instant huge

! Advantage: space proportional to amount of info. Lesson: know space and time costs. ! Disadvantage: can only get to next item quickly. ■ Axiom 1: there is never enough space. Time to determine coefficient of xk. ■ Axiom 2: there is never enough time.

11 12

Overview of Linked Lists in C Linked List for Polynomial poly1.c Not directly built in to C language. Need to know: C code to represent struct *link; 9 5 of x + 3x + 7. struct node { How to associate pieces of information. ■ Statically, using nodes. int coef; define node to

■ User-define type using struct. int exp; store two integers memory address link next; ■ Include struct field for coefficient and exponent. of next node };

How to specify links. int main(void) {

■ Include struct field for POINTER to next linked list element. struct node p, q, ; p.coef = 1; p.exp = 9; q.coef = 3; q.exp = 5; How to reserve memory to be used. initialize data r.coef = 7; r.exp = 0; ■ Allocate memory DYNAMICALLY (as you need it). p.next = &q; ■ malloc() link up nodes q.next = &r; r.next = NULL; How to use links to access information. return 0; ■ -> and . operators }

13 14 Linked List for Polynomial Better Programming Style

poly3.c C code to represent poly2.c Write separate 9 5 #include of x + 3x + 7. function to #include memory allocation ■ Statically, using nodes. typedef struct node *link; and initialization. link NEWnode(int c, int e, link n) { ■ Dynamically using links. struct node { . . .}; link x = malloc(sizeof *x); if (x == NULL) { int main(void) { link x, y, z; check if printf("Out of memory.\n"); malloc fails exit(EXIT_FAILURE); x = malloc(sizeof *x); } initialize data x->coef = 1; x->exp = 9; x->coef = c; x->exp = e; x->next = n; y = malloc(sizeof *y); return x; y->coef = 3; y->exp = 5; } allocate enough z = malloc(sizeof *z); memory to store node int main(void) { z->coef = 7; z->exp = 0; Initialize link x = NULL; x->next = y; pointers to NULL x = NEWnode(7, 0, x); y->next = z; link up nodes of list x = NEWnode(3, 5, x); z->next = NULL; x = NEWnode(1, 9, x); return 0; Study this code: tip of iceberg! return 0; } }

15 16

Review of Stack Stack Implementation With Linked Lists

In Lecture P5, we created ADT for stack. stacklist.c

■ We implemented stack using arrays. #include

■ Now, we give alternate implementation using linked lists. #include "STACK.h" typedef struct STACKnode* link; client.c struct STACKnode { STACK.h int item; standard linked #include "STACK.h" link next; list data structure void STACKinit(void); }; int STACKisempty(void); int main(void) { void STACKpush(int); int a, b; static to make static link head = NULL; head points to int STACKpop(void); . . . it a true ADT top node on stack void STACKshow(void); STACKinit(); void STACKinit(void) { STACKpush(a); head = NULL; client uses , without . . . } regard to how it is represented b = STACKpop(); or implemented. return 0; int STACKisempty(void) { } return head == NULL; }

17 18 Stack Implementation With Linked Lists Stack Implementation With Linked Lists stacklist.c (cont)

int STACKpop(void) { stacklist.c (cont) int item; allocate memory and link NEWnode(int item, link next) { if (head == NULL) { initialize new node link x = malloc(sizeof *x); printf("Stack underflow.\n"); if (x == NULL) { exit(EXIT_FAILURE); printf("Out of memory.\n"); } exit(EXIT_FAILURE); item = head->item; } link x = head->next; free malloc x->item = item; x->next = next; free(head); is opposite of : gives memory back to system return x; head = x; } return item; void STACKpush(int item) { } insert at beginning head = NEWnode(item, head); traverse linked list of list } void STACKshow(void) { link x; for (x = head; x != NULL; x = x-next) printf("%d\n", x->item); } 19 20

Implementing Stacks: Arrays vs. Linked Lists Conclusions

We can implement a stack with either array or linked list, and switch Whew, lots of material in this lecture! implementation without changing interface or client. %gcc client.c stacklist.c Pointers are useful, but confusing. OR %gcc client.c stackarray.c Study these slides and carefully read relevant material.

Which is better?

■ Array ! Requires upper bound MAX on stack size. ! Uses space proportional to MAX.

■ Linked List ! No need to know stack size ahead of time. ! Requires extra space to store pointers. ! Dynamically memory allocation is slower.

21 22 Pointers and Arrays

on arizona, Lecture P8: Extra Slides avg.c int is 32 bits (4 ) ⇒ #include 4 offset #define N 64 "Pointer arithmetic" int main(void) { &a[0] = a+0 = D000 int a[N] = {84, 67, 24, ..., 89, 90}; &a[1] = a+1 = D004 int i, sum; &a[2] = a+2 = D008 for (i = 0; i < N; i++) a[0] = *a = 84 sum += a[i]; a[1] = *(a+1) = 67 a[2] = *(a+2) = 24 printf("%d\n", sum / N); return 0; }

Memory address D000 D004 D008 .. D0F8 D0FC .. Value 84 67 24 .. 89 90 ..

24

Pointers and Arrays Passing Arrays to Functions

integer (on arizona) takes 4 Pass array to function.

bytes ⇒ 4 byte offset ■ Pointer to array element 0 is passed instead. Just to stress that a[i] really means *(a+i): avg.c "Pointer arithmetic" 2[a] = *(2+a) = 24 #include &a[0] = a+0 = D000 #define N 64 This is legal C, but don't ever &a[1] = a+1 = D004 do this at home!!! &a[2] = a+2 = D008 int average(int b[], int n) { receive the value D000 from main a[0] = *a = 84 int i, sum; a[1] = *(a+1) = 67 for (i = 0; i < n; i++) a[2] = *(a+2) = 24 sum += b[i]; return sum / n; }

int main(void) { int a[N] = {84, 67, 24, ..., 89, 90}; Memory address D000 D004 D008 .. D0F8 D0FC .. printf("%d\n", average(a, N)); passes &a[0] = D000 return 0; to function Value 84 67 24 .. 89 90 .. }

25 26 Why Pass Array as Pointer? Passing Arrays to Functions

Advantages. Many C programmers use int *b instead of int b[] in function ! Efficiency for large arrays – don't want to copy entire array. prototype.

! Easy to pass "array slice" of "sub-array" to functions. ■ Emphasizes that array decays to pointer when passed to function.

avg.c

int average(int b[], int n) { average function an equivalent function int i, sum; for (i = 0; i < n; i++) int average(int b[], int n) { int average(int *b, int n) { sum += b[i]; int i, sum; int i, sum; return sum / n; for (i = 0; i < n; i++) for (i = 0; i < n; i++) } sum += b[i]; sum += b[i]; return sum / n; return sum / n; int main(void) { } } . . . res = average(a+5, 10); compute average of . . . a[5] through a[14] }

27 28