I. Syntax and Smantics of Pointers in C A. Overview 1. Concept of Pointers ------------------------------------------ THE POINTER CONCEPT A pointer in C is Think of memory as char memory[HUGE]; int i = 20; memory[i] = 'U'; printf("memory[%d] is '%c'\n", i, memory[i]); // same thing with pointers Pointer operators: dereference: address of: printf("*(memory + %d) is '%c'\n", i, *ptc); printf("memory + i is %lx\n", (uintptr_t)(memory + i)); printf("&memory[i] is %lx\n", (uintptr_t)(&memory[i])); Basic principle: each address is ------------------------------------------ 2. Uses of Pointers ------------------------------------------ USES OF POINTERS - Provides indirect addressing - Allows access to - Can represent - Efficient passing - Can modularize ------------------------------------------ B. Syntax 1. Pointer Types ------------------------------------------ POINTER TYPES Expressions related to pointer types: ::= ... | * | & Pointer type syntax: ::= ... | * Pointer variable declaration syntax: * ; Examples: int *ptoi; char *ptc; int **ptpti; Pointer types may combine with other types: char *argv[10]; is such that argv[3] has type char * so it is an ------------------------------------------ 2. constant variables and pointers ------------------------------------------ CONST The type qualifier const can be used to declare Examples: const int seven = 7; const char nc = '\0'; const int *pto7 = &seven; illegal with the above: seven = 8; // illegal! seven++; // illegal! *pto7 = 8; // illegal! *pto7 -= 1; // illegal! ------------------------------------------ ------------------------------------------ POINTERS CAN ALSO BE CONST POINTERS TO CONSTs vs. CONST POINTERS const int seven = 7; int eight = 8; const int *pto7 = &seven; int *const cpto8 = &eight; Here pto7 is and cpto8 is Allowed or illegal? *pto7 = 9; pto7 = &eight; *cpto8 = 9; cpto8 = &seven; ------------------------------------------ C. semantics ------------------------------------------ ABSTRACT MODEL OF POINTERS IN C 1. The program's memory is like 2. A pointer identifies 3. If p has type (T *), then *p, of type T, 4. If x has type T, then &x, of type (T *), 5. If p has type (T *), then p+1 is ------------------------------------------ ------------------------------------------ THE VIEW FROM THE MACHINE 1. The computer's memory is a big array of chars 2. A pointer is an index into that array = an address 3. *p is the contents of the memory at that address (load indirect or store indirect) 4. &x is the address of x 5. p+1 adds sizeof(typeof(*p)) to address p ------------------------------------------ 1. parameter passing in C ------------------------------------------ PARAMETER PASSING IN C Arguments to functions are always Expression of type Value is ================================== int an int char a char float a double double a double T [] T * Arrays are passed ------------------------------------------ ------------------------------------------ RETURN TYPES Can't return an array in C, char [] f() { ... } // illegal! Must return the pointer equivalent char * f() { ... } // type is ok ------------------------------------------ 2. pointers into arrays ------------------------------------------ TECHNICAL RESTRICTION ON BOUNDS - If you have a pointer into an array of type T elements T a[10]; T *p = a; // equivalently &a[0] then p is only However, ------------------------------------------ ------------------------------------------ DANGLING POINTERS def: a *dangling pointer* is a pointer that points to memory that is Example: #include #include // Causes a dangling pointer, bad code! int * getspace() { int x = 7; return &x; // wrong! creates dangling pointer } // Demonstrates the effect of dangling pointers int main() { int *ptoi = getspace(); // now disaster ensures... printf("*ptoi is %d\n", *ptoi); *ptoi = 8; return EXIT_SUCCESS; } ------------------------------------------ ------------------------------------------ TO AVOID DANGLING POINTERS 1. Never return a pointer 2. Use malloc to allocate long-lived data #include #include // return space for an int on the heap int * getspace() { int *ptoi = malloc(sizeof(int)); return ptoi; } // Demonstrates the use of malloc int main() { int *ptoi = getspace(); // now things are okay *ptoi = 8; printf("*ptoi is %d\n", *ptoi); return EXIT_SUCCESS; } ------------------------------------------ II. examples using pointers A. capturing patterns of assignments 1. swap ------------------------------------------ SWAPPING PATTERN How do you swap the values of 2 variables x and y? int x; int y; // code to swap them ------------------------------------------ Is it annoying to have to do that several times in code? How can we fix annoying repeated code like that? ------------------------------------------ A FAILED ATTEMPT AT A FUNCTION #include #include // wrong! void wrong_swap(int x, int y) { int temp = x; x = y; y = temp; } // demonstrate problem with wrong_swap int main() { int a = 9; int b = 100; printf("a is %d and b is %d\n", a, b); printf("calling wrong_swap(a, b)\n"); wrong_swap(a, b); printf("a is %d and b is %d\n", a, b); return 0; } ------------------------------------------ What's wrong with this? ------------------------------------------ SWAP FUNCTION How can we swap the values in the caller's variables? void swap( ------------------------------------------ ------------------------------------------ INSERTION SORT Want to put the elements of an array of ints, a, into nondecreasing order so that if sz is the size of a, then for all 0 <= i < j < sz: a[i] <= a[j] Algorithm: compare all pairs a[i] and a[j], swap them if they are out of order #include "swap.h" // requires: a is allocated and has elements with indexes low to high-1 // ensures: result is true just when the elements a[low .. high-1] // are in non-decreasing order extern bool sorted(const int a[], int low, int high); // requires: a is allocated and has at least sz elements // assigns: a[*] // ensures: for all 0 <= i < j < sz: a[i] <= a[j] void bubble_sort(int a[], int sz) { int i = 1; ok(sorted(a, 0, i) && i <= sz, "for invariant"); for (i = 1; i < sz; i++) { int j = i; ok(sorted(a, j, i) && i <= sz && 0 <= j && j <= i, "init while invariant"); while (0 < j && a[j-1] > a[j]) { swap(&a[j-1], &a[j]); ok (a[j-1] < a[j], "swap restored order"); j -= 1; ok(sorted(a, j, i) && i <= sz && 0 <= j && j <= i, "while invariant again"); } ok(sorted(a, 0, i), "sorted to %d", i); ok(i <= sz, "i <= sz"); ok(sorted(a, 0, i) && i <= sz, "for invariant again"); } ok(sorted(a, 0, i) && i == sz, "for invariant"); ok(sorted(a, 0, sz), "postcondition"); } ------------------------------------------ B. multi-assign ------------------------------------------ MULTIPLE ASSIGNMENT Python has a statement of the form x,y = E1, E2 which evaluates E1 and E2, then assigns them to x and y. How can we write this in C? ------------------------------------------ III. Friday problems with C pointers A. capturing patterns of assignments 1. initialize an array ------------------------------------------ FOR YOU TO DO write a function extern void init_array(double *a, int sz, double val); that takes an array a of doubles and initializes each element with index 0..sz-1 to the value val. (Assume that val is not NaN.) ------------------------------------------ B. Code that uses swap 1. reverse an array ------------------------------------------ FOR YOU TO DO Write a function extern void reverse(char *s); that takes a null-terminated string s, and reverses it in place. So, if the length of s is len, then at the end *s is the old value of *(s+len-1) and vice versa *(s+1) is the old value of *(s+len-2) and vice versa *(s+2) is the old value of *(s+len-3) and vice versa etc. For example: char str[] = {'U', 'C', 'F'}; reverse(str); ok(*str == 'F'); ok(*(str+1) == 'C'); ok(*(str+2) == 'U'); ------------------------------------------ 2. insertion sort ------------------------------------------ FOR YOU TO DO Write a function, extern bool palindrome(const char *sentence) that takes a string, sentence, and returns true just when sentence is a palindrome, so that it reads the same forwards and backwards. Note that palindrome may not change any characters. ------------------------------------------