CSC 270 Survey of Programming Languages C Lecture

  • Slides: 54
Download presentation
CSC 270 – Survey of Programming Languages C Lecture 6 – Pointers and Dynamic

CSC 270 – Survey of Programming Languages C Lecture 6 – Pointers and Dynamic Arrays Modified from Dr. Siegfried

What is a Pointer? • A pointer variable type is a variable whose values

What is a Pointer? • A pointer variable type is a variable whose values are memory addresses. • We call it a pointer because we envision the address as “pointing” to where the value is stored. • Deferencing a pointer gets the value at that memory address • Reference parameters make use of pointers. • Extra info: Arrays are passed by reference because the name of an array (without an index following it) is a pointer to where the array is stored.

Why use pointers Picture From Griffiths, David and Dawn Griffiths. Head First C. O'Reilly:

Why use pointers Picture From Griffiths, David and Dawn Griffiths. Head First C. O'Reilly: 2012, p 42.

Work with Variable Addresses • Get the address of a variable and put it

Work with Variable Addresses • Get the address of a variable and put it into a pointer – int x = 4; – printf("x lives at %pn", x); – int * address_of_x = &x; • Get the contents at that address – int value_stored = *address_of_x • * is the opposite of & Picture and text source From Griffiths, David and Dawn Griffiths. Head First C. O'Reilly: 2012, p 48.

Pointer Variables • When we write double x; we are saying that there is

Pointer Variables • When we write double x; we are saying that there is a double-precision value stored in memory and x is the value at that location. • When we write double *p we are saying that p is a pointer to a double value that is stored in memory and that p’s value is the address at which the value is stored. (Read backwards) Note: could be double* p instead.

Change the value using a pointer • Use the dereferenced pointer to get at

Change the value using a pointer • Use the dereferenced pointer to get at the value – *address_of_x = 99; Picture and text source From Griffiths, David and Dawn Griffiths. Head First C. O'Reilly: 2012, p 48.

Assign and Dereference Pointers #include <stdio. h> int main(void) { int a; int *

Assign and Dereference Pointers #include <stdio. h> int main(void) { int a; int * a. Ptr; a = 7; a. Ptr = &a; printf("The address of a is %pn. The value of a. Ptr is %pn", &a, a. Ptr); printf("The value of a is %dn. The value of *a. Ptr is %dn", a, *a. Ptr); printf("n. The result of &*a. Ptr is %pn and the value of *&a. Ptr is %pn", &*a. Ptr, *&a. Ptr); printf("n. The result of *&a is %dn", *&a); //CANT DO THIS because you cannot deference an int: printf("%d", *a); }

Deferencing Result • • The address of a is 0 x 7 fff 22344

Deferencing Result • • The address of a is 0 x 7 fff 22344 cfc The value of a. Ptr is 0 x 7 fff 22344 cfc The value of a is 7 The value of *a. Ptr is 7 • The result of &*a. Ptr is 0 x 7 fff 22344 cfc • and the value of *&a. Ptr is 0 x 7 fff 22344 cfc • The result of *&a is 7

Declaring and Using Pointer Variables • We can declare several pointer variables in the

Declaring and Using Pointer Variables • We can declare several pointer variables in the same statement, even together with variable of the type to which they point: int v 1, v 2, v 3, *p 1, *p 2, *p 3; • We can assign values to pointers using the referencing operator (&): p 1 = &v 1; /* p 1 holds the address where v 1 is stored. */

Using Pointers v 1 = 0; p 1 = &v 1; *p 1 =

Using Pointers v 1 = 0; p 1 = &v 1; *p 1 = 42; printf("%dn", v 1); printf("%dn", *p 1); Output 42 42

Pointers and the Assignment Operation • Assign a pointer to another pointer p 2

Pointers and the Assignment Operation • Assign a pointer to another pointer p 2 = p 1 printf("%dn", *p 2); will also produce 42 (unless v 1’s value was changed).

p 1 = p 2 Before After p 1 8 p 2 9

p 1 = p 2 Before After p 1 8 p 2 9

*p 1 = *p 2 Before After p 1 8 p 1 9 p

*p 1 = *p 2 Before After p 1 8 p 1 9 p 2 9

malloc()point to memory not already holding a variable • The library function malloc() is

malloc()point to memory not already holding a variable • The library function malloc() is used to allocate memory for a data item and then to assign its address to a pointer variable. • The prototype for malloc() is void* malloc (size_t size); where size_t is an unsigned integer type • Variables that are created using malloc() are called dynamically allocated variables. • Found in stdlib. h

malloc()- An Example p 1 = (int *) malloc(sizeof(int)); scanf("%d", p 1); *p 1

malloc()- An Example p 1 = (int *) malloc(sizeof(int)); scanf("%d", p 1); *p 1 = *p 1 + 7; printf("%d", *p 1);

free() • The function free() eliminates a dynamic variable and returns the memory that

free() • The function free() eliminates a dynamic variable and returns the memory that the dynamic variable occupied to the heap. It can be re-used. • The prototype: void free (void* ptr); • After the delete statement, p’s value is undefined.

Demo Dynamic Variables #include <stdio. h> #include <stdlib. h> int main (void){ int *p

Demo Dynamic Variables #include <stdio. h> #include <stdlib. h> int main (void){ int *p 1, *p 2; p 1 = (int *) malloc(sizeof(int)); *p 1 = 42; p 2 = p 1; printf ("*p 1 == %dn *p 2 == %dn", *p 1, *p 2); *p 2 = 53; puts ("nn. After *p 2 = 53: n"); printf("*p 1 == %dn *p 2 == %dn", *p 1, *p 2); p 1 = (int *) malloc(sizeof(int));

*p 1 = 88; *p 2 = 33; puts ("nn. After *p 1 =

*p 1 = 88; *p 2 = 33; puts ("nn. After *p 1 = 88 and *p 2 = 33"); puts("and created new var for p 1 to reference: n"); printf("*p 1 == %dn *p 2 == %dn", *p 1, *p 2); free(p 1); // why not free p 1 before second malloc? ? ? free(p 2); return(0); }

Output from Basic. Pointer. c (demo dynamic var) *p 1 == 42 *p 2

Output from Basic. Pointer. c (demo dynamic var) *p 1 == 42 *p 2 == 42 After *p 2 = 53: *p 1 == 53 *p 2 == 53 After *p 1 = 88 and *p 2 = 33 and created new var for p 1 to reference: *p 1 == 88 *p 2 == 33

Explaining Basic. Pointer. c int *p 1, *p 2; p 1 = (int *)

Explaining Basic. Pointer. c int *p 1, *p 2; p 1 = (int *) malloc(sizeof(int)); p 1 ? p 1 p 2 ? ?

Explaining Basic. Pointer. c *p 1 = 42; 42 p 1 p 2 =

Explaining Basic. Pointer. c *p 1 = 42; 42 p 1 p 2 = p 1; ? p 1 p 2 42

Explaining Basic. Pointer. c *p 2 = 53; p 1 p 2 p 1

Explaining Basic. Pointer. c *p 2 = 53; p 1 p 2 p 1 = (int *) malloc(sizeof(int)); 53 p 1 ? p 2 53

Explaining Basic. Pointer. c *p 1 = 88; *p 2 = 33 p 1

Explaining Basic. Pointer. c *p 1 = 88; *p 2 = 33 p 1 88 p 2 33

Basic Memory Management • The heap is a special area of memory reserved for

Basic Memory Management • The heap is a special area of memory reserved for dynamically allocated variables. • Compilers would return NULL if there wasn’t enough memory when calling malloc(). • It could potentially cause the program to abort execution.

Stopping Errors with malloc() int *p; p = (int *) malloc(sizeof(int)); if (p ==

Stopping Errors with malloc() int *p; p = (int *) malloc(sizeof(int)); if (p == NULL) { printf("Insufficient memoryn"); exit(1); } /* If malloc()succeeded, the program continues here */

NULL • NULL is actually the number 0, but we prefer to think of

NULL • NULL is actually the number 0, but we prefer to think of it as a special-purpose value. . • NULL’s definition appears in <cstdlib>, and <stdlib. h> • NULL can be assigned to a pointer variable of any type.

Dangling Pointers • A dangling pointer is an undefined pointer. It either has no

Dangling Pointers • A dangling pointer is an undefined pointer. It either has no address assigned yet or what it pointed to is now gone. • If p is a dangling pointer, then *p references memory that has been returned to the heap and the result is unpredictable. • C has no built-in mechanism for checking for dangling pointers. – For this reason, it is always a good idea to set dangling pointers to NULL.

Dynamic Variables • Variables created using the malloc function are called dynamic variables (they

Dynamic Variables • Variables created using the malloc function are called dynamic variables (they are created and destroyed while the program is running. • Storage for local variables are allocated when the function is called and de-allocated when the function call is completed. They are called automatic variables because this is all done automatically. • Variables declared outside any function or class definition are called external (or global) variables. They are statically allocated because their storage is allocated when the program is translated.

typedef • You can define a pointer type name so that pointer variables can

typedef • You can define a pointer type name so that pointer variables can be declared like other variables. (and to help with pointer math) • E. g. , typedef int * Int. Ptr; Int. Ptr p; // equivalent to int *p; • typedef can be used to define any kind of data type: typedef double Kilometers; Kilometers distance;

Dynamic Arrays • A dynamic array is an array whose size is not specifically

Dynamic Arrays • A dynamic array is an array whose size is not specifically when you write the program. • Example int a[10]; typedef int *Int. Ptr; Int. Ptr p; … p = a; /* p[i] refers to a[i] */

Array. Demo. c // Program to demonstrate that an array variable is // a

Array. Demo. c // Program to demonstrate that an array variable is // a kind of pointer variable #include <stdio. h> typedef int* Int. Ptr; int { main(void) Int. Ptr int p; a[10]; index; for (index = 0; index < 10; a[index] = index; index++)

p = a; for (index = 0; index < 10; index++) printf("%d ", p[index]);

p = a; for (index = 0; index < 10; index++) printf("%d ", p[index]); printf("n"); for (index = 0; index < 10; index++) p[index] = p[index] + 1; for (index = 0; index < 10; index++) printf("%d ", a[index]); printf("n"); return(0); } Output 0 1 2 3 4 5 6 7 8 9 10

Creating and Using Dynamic Arrays • You do not always know in advance what

Creating and Using Dynamic Arrays • You do not always know in advance what size an array should be. Dynamic arrays allow the programmer to create arrays that are flexible in size: typedef double *Double. Ptr; Double. Ptr d; d = (double *) malloc (10*sizeof(double));

Dyn. Array. Demo. c // Searches a list of numbers entered at the //

Dyn. Array. Demo. c // Searches a list of numbers entered at the // keyboard #include <stdio. h> #include <stdlib. h> typedef int* Int. Ptr; void fill. Array(int a[], int size); // Precondition: size is the size of the array a // Postcondition: a[0] through a[size-1] have been // filled with values read from the keyboard.

int search(int a[], int size, int target); // Precondition: size is the size of

int search(int a[], int size, int target); // Precondition: size is the size of the array a // The array elements a[0] through a[size-1] have // values. // If target is in the array, returns the first index // of target // If target is not in the array, returns -1. int { main(void) printf("This program search a list of " " numbers. n"); int array. Size, target; int location;

printf("How many numbers will be on the " "listt? "); scanf("%d", &array. Size); Int.

printf("How many numbers will be on the " "listt? "); scanf("%d", &array. Size); Int. Ptr a; a = (int *) malloc(array. Size*sizeof(int)); fill. Array(a, array. Size); printf("Enter a value to search for: t? "); scanf("%d", &target); location = search(a, array. Size, target);

if (location == -1) printf("%d is not in the array. n", target); else printf("%d

if (location == -1) printf("%d is not in the array. n", target); else printf("%d is element %d in the array. n" , target, location); free(a); return(0); }

// Uses the library <stdio. h>: void fill. Array(int a[], int size) { printf("Enter

// Uses the library <stdio. h>: void fill. Array(int a[], int size) { printf("Enter %d integers. ", size); int index; for ( index = 0; index < size; index++) scanf("%d", &a[index]); }

int search(int a[], int size, int target) { int index = 0; while ((a[index]

int search(int a[], int size, int target) { int index = 0; while ((a[index] != target) && (index < size)) index++; if (index == size) /* If target is not in a */ index = -1; return index; }

Why use free(a); ? • The free(a) function call is necessary if the program

Why use free(a); ? • The free(a) function call is necessary if the program will do other things after finishing its use of a dynamic array, so the memory can be reused for other purposes.

Ptr. Demo. c #include <stdio. h> <stdlib. h> int* doubler (int a[], int size);

Ptr. Demo. c #include <stdio. h> <stdlib. h> int* doubler (int a[], int size); /* * Precondition: size is the size of the array a * A indexed variables of a have values. * Returns: a pointer to an array of the same size * as a in which each index variable is * double the corresponding element in a. */

int { main(void) int a[] = {1, 2, 3, 4, 5}; *b; b =

int { main(void) int a[] = {1, 2, 3, 4, 5}; *b; b = doubler(a, 5); int i; printf("array a: n"); for (i = 0; i < 5; i++) printf("%d ", a[i]); printf("n"); printf("Array b: n"); for (i = 0; i < 5; i++) printf("%d ", b[i]);

printf("n"); free(b); return(0); } int { *doubler(int a[], int size) int *temp; temp =

printf("n"); free(b); return(0); } int { *doubler(int a[], int size) int *temp; temp = (int *) malloc(size*sizeof(int)); int i; for (i = 0; i < size; i++) temp[i] = 2*a[i]; return temp; }

Output from Ptr. Demo. cpp array 1 2 3 Array 2 4 6 a:

Output from Ptr. Demo. cpp array 1 2 3 Array 2 4 6 a: 4 5 b: 8 10

Pointer Arithmetic • If p is a pointer, p++ increment p to point to

Pointer Arithmetic • If p is a pointer, p++ increment p to point to the next element and p += i; has p point i elements beyond where it currently points. • Example typedef double* Double. Ptr; Double. Ptr d; d = new double[10]; • d +1 points to d[1], d+2 points to d[2]. • If d = 2000, d+1 = 2008 (double use 4 bytes of memory).

Pointer Arithmetic – An Example for (i = 0; i < array. Size; i++)

Pointer Arithmetic – An Example for (i = 0; i < array. Size; i++) printf("%d ", *(d+i)); is equivalent to for (i = 0; i < array. Size; i++) printf("%d ", d[i]);

Pointers and ++ and - • You can also use the increment and decrement

Pointers and ++ and - • You can also use the increment and decrement operators, ++ and – to perform pointer arithmetic. • Example • d++ advances the pointer to the address of the next element in the array and d–- will set the pointer to the address of the previous element in the array.

Multidimensional Dynamic Arrays • Multidimensional dynamic arrays are really arrays of arrays or arrays

Multidimensional Dynamic Arrays • Multidimensional dynamic arrays are really arrays of arrays or arrays of arrays, etc. • To create a 2 -dimensional array of integers, you first create an array of pointers to integers and create an array of integers for each element in the array.

Creating Multidimensional Arrays // Create a data type for to integers typedef int *

Creating Multidimensional Arrays // Create a data type for to integers typedef int * Int. Array. Ptr; // Allocate an array of 3 integer pointers Int. Array. Ptr *m = (int**)malloc(3*sizeof (int *)); // Allocate for 3 arrays of 4 integers each. int i; for ( i = 0; i < 3; i++) m[i] = (int *) malloc(4*sizeof(int)); // Initialize them all for ( i = 0; I < n; for (int j = 0; m[i][j] = to 0 i++) j < n; 0; j++)

free • Since m is an array of array, each of the arrays created

free • Since m is an array of array, each of the arrays created with malloc() in the for loop must be returned to the heap using a call to free() and then afterward, m itself must be returned using free().

Mult. Array. Demo. c #include<stdio. h> #include<stdlib. h> typedef int*Int. Array. Ptr; int {

Mult. Array. Demo. c #include<stdio. h> #include<stdlib. h> typedef int*Int. Array. Ptr; int { main(void) int d 1, d 2; int i, j; Int. Array. Ptr *m; printf("Enter the row and column dimensions" " of the array: t"); scanf("%d%d", &d 1, &d 2);

m = (Int. Array. Ptr *) malloc(d 1 *sizeof(Int. Array. Ptr)); for (i =

m = (Int. Array. Ptr *) malloc(d 1 *sizeof(Int. Array. Ptr)); for (i = 0; i < d 1; i++) m[i] = (int *) malloc(d 2 * sizeof(int)); /* m is now a d 1 -by-d 2 array. */ printf("Enter %d rows of %d integers each: n", d 1, d 2); for (i = 0; i < d 1; i++) for (j = 0; j < d 2; j++) scanf("%d", &m[i][j]); printf("Echoing the two-dimensional array: n");

for (i = 0; i < d 1; i++){ for (j = 0; j

for (i = 0; i < d 1; i++){ for (j = 0; j < d 2; j++) printf("%d ", m[i][j]); printf("n"); } for (i = 0; i < d 1; free(m[i]); free(m); return (0); } i++)

Output Enter the row and column dimensions of the array: 3 4 Enter 3

Output Enter the row and column dimensions of the array: 3 4 Enter 3 rows of 4 integers each: 1 2 3 4 5 6 7 8 9 0 1 2 Echoing the two-dimensional array: 1 2 3 4 5 6 7 8 9 0 1 2