Arrays
LAST TODAY NEXT Integers Array mechanics Searching arrays Memory model Correctness Aliasing Safety
Dataypes so far • Basic (a.k.a. small types) : int, string, bool, char • Integers • represent numbers (rendered using 2’s complement) • represent bit patterns • Safety constraints on operations • x / y, x % y • x << k, x >> k
Learning resources
C0 Memory Model Local Memory int square(int x){ x return x * x; } Contains values of local variables May only contain values of small types
C0 Memory Model Local Memory int main(){ x int x = 100; int y = square(x); y return y; } Contains values of local variables May only contain values of small types
Function calls Local Memory main x int square(int x) { 10 return x * x; y } 100 int main(){ int x = 10; square int y = square(x); x 10 return y; } Contains values of local variables May only contain values of small types
A new dataype • int, string, bool, char small • t[] array whose elements are of type t not small
C0 Memory Model Local Memory Allocated Memory Contains values of local variables We can have addresses to the memory cells May only contain values of small types and store those addresses in local memory
C0 array facts alloc_array(t, n) A[i] • Initializes to a default value of type t • Indexable by integers [0, n) • Precondition: n >= 0 • Precondition: 0 <= i < n • Postcondition: length of allocated array is n
Arrays in C0 examples with coin
Arrays in C0 --> int[] A = alloc_array(int, 5); A is 0x13500000 (int[] with 5 elements) memory address
int[] X = alloc_array(int, 3); X[0] = 5; X[1] = 6; X[2] = 7; Local Memory Allocated Memory 0xB8 5 6 7 X 0xB8 memory address
int[] X = alloc_array(int, 3); X[0] = 5; X[1] = 6; X[2] = 7; int[] Y = X; Local Memory Allocated Memory 0xB8 5 6 7 X 0xB8 Y 0xB8
int[] X = alloc_array(int, 3); X[0] = 5; X[1] = 6; X[2] = 7; int[] Y = X; Y[2] = 9; Local Memory Allocated Memory 0xB8 5 6 9 X 0xB8 Y 0xB8
int[] X = alloc_array(int, 3); X[0] = 5; X[1] = 6; X[2] = 7; int[] Y = X; Y[2] = 9; X == Y; true Local Memory Allocated Memory 0xB8 5 6 9 X 0xB8 Y 0xB8
int[] X = alloc_array(int, 3); X[0] = 5; X[1] = 6; X[2] = 7; int[] Y = X; Y[2] = 9; int[] Z = alloc_array(int, 3); Z[0] = 5; Z[1] = 6; Z[2] = 9; X == Z; false Local Memory Allocated Memory 0xB8 5 6 9 X 0xB8 Y 0xB8 0xC4 5 6 9 Z 0xC4
int[] X = alloc_array(int, 3); X[0] = 5; X[1] = 6; X[2] = 7; int[] Y = X; int[] Z = alloc_array(int, 3); X = alloc_array(int, 3); old X still accessible via Y Y = alloc_array(int, 3); old X will be garbage collected
Contracts for array operations • alloc_array(t, n) • //@requires n >= 0 • //@ensures \length(result) == n • A[i] (both read and write) • //@requires 0 <= i && i < \length(A) • \length(A) • //@ensures \result >= 0
Example: copying an array • Write function array_copy , which will copy contents of a given array to a new array and return the new array • What should the parameters be? • Pre and post conditions • Code example using array_copy: int[] X = alloc_array(int, 3); int[] Y = array_copy(X,…); Y should be a new array containing the same elements as in X!
First attempt int[] array_copy(int[] A) { return A; } client(caller,user) code int[] X = alloc_array(int, 3); int[] Y = array_copy(X); Y ends up being an alias for X, not what we want!
Second attempt int[] array_copy(int[] A) { int[] B = alloc_array(int,???); … } There is no primitive for getting length of a C0 array. \length(A) is allowed only in contracts.
Second attempt int[] array_copy(int[] A, int n) { int[] B = alloc_array(int,n); … safe? } correct? client(caller,user) code int[] X = alloc_array(int, 3); int[] Y = array_copy(X,5); should not be allowed
Precondition added int[] array_copy(int[] A, int n) //@requires n == \length(A); { int[] B = alloc_array(int,n); … return B; } client code int[] X = alloc_array(int, 3); int[] Y = array_copy(X,3);
Precondition added int[] array_copy(int[] A, int n) //@requires n == \length(A); { int[] B = alloc_array(int,n); B = A; return B; } client code int[] X = alloc_array(int, 3); int[] Y = array_copy(X,3); B is an alias to A, after array_copy returns, B is garbage collected.
Third attempt int[] array_copy(int[] A, int n) //@requires n == \length(A); { int[] B = alloc_array(int,n); for (int i = 0; i < n; i++) { B[i] = A[i]; } return B; }
Safety on the function side int[] array_copy(int[] A, int n) //@requires n == \length(A); { int[] B = alloc_array(int,n); for (int i = 0; i < n; i++) { B[i] = A[i]; } return B; } • Is A[i] safe? } need to show 0 <= i < length of A/B • Is B[i] safe? Using precondition, loop guard, and postcondition of alloc_array
Safety on the function side int[] array_copy(int[] A, int n) //@requires n == \length(A); { int[] B = alloc_array(int,n); for (int i = 0; i < n; i++) //@loop_invariant 0 <= i; show that it is a valid loop invariant { B[i] = A[i]; } return B; }
Proof INIT: obvious int[] array_copy(int[] A, int n) PRES: //@requires n == \length(A); { assume 0<= i, and show 0 <= i’ int[] B = alloc_array(int,n); for (int i = 0; i < n; i++) i’ = i + 1 //@loop_invariant 0 <= i; i + 1 >= 0 { B[i] = A[i]; ( i ! = int_max() because i < n } return B; by the loop guard) }
int[] array_copy(int[] A, int n) //@requires n == \length(A); Safety on the caller side int main() { int[] I = alloc_array(int, 3); for (int i=0; i<3; i++) { I[i] = i+5; // I is [5, 6, 7] } int[] J = array_copy(I,3); int[] K = array_copy(J,3); return 0; } • Is int[] J = array_copy(I,3) safe? • Is int[] K = array_copy(J,3) safe? What is length of J?
Postcondition added int[] array_copy(int[] A, int n) //@requires n == \length(A); //@ensures \length(\result) == n; { int[] B = alloc_array(int,n); for (int i = 0; i < n; i++) //@loop_invariant 0 <= i; { B[i] = A[i]; } return B; }
Effects visible to the client? int[] array_copy(int[] A, int n) //@requires n == \length(A); //@ensures \length(\result) == n; { int[] B = alloc_array(int,n); for (int i = 0; i < n; i++) //@loop_invariant 0 <= i; { B[i] = A[i]; } if (n > 0) A[0] = 42; visible to caller return B; }
int[] array_copy(int[] A, int n) //@requires n == \length(A); //@ensures \length(\result) == n; { int[] B = alloc_array(int,n); for (int i = 0; i < n; i++) //@loop_invariant 0 <= i; { B[i] = A[i]; } not visible to caller A = alloc_array(int, 10); if (n > 0) A[0] = 42; return B; }
Recommend
More recommend