CS31 Discussion 1E Spring 17 : week 08 TA: Bo-Jhang Ho bojhang@cs.ucla.edu Credit to former TA Chelsea Ju
Project 5 - Map cipher to crib Approach 1: For each pair of positions, check two letters in cipher and crib are both identical or different For each pair of positions pos1 and pos2, cipher[pos1] == cipher[pos2] should equal to crib[pos1] == crib[pos2] Approach 2: Get the positions of the letter and compare For each position pos, indexes1 = getallpositions(cipher, pos, cipher[pos]) indexes2 = getallpositions(crib, pos, crib[pos]) indexes1 should equal to indexes2
Project 5 - Map cipher to crib Approach 3: Generate the mapping We first have a mapping array char cipher2crib[128] = { \0 ; Then whenever we attempt to map lettera in cipher to letterb in crib, we first check whether it violates the previous setup: Is cipher2crib[lettera]!= \0? // implies lettera has been used Then cipher2crib[lettera] should equal to letterb If no violation happens, cipher2crib[lettera] = letterb;
Road map of CS31 String Array Function Class Variable If / else Loops Pointer!!
Cheat sheet Data type int *a; a is a variable, whose data type is int * a stores an address of some integer Use as verbs & - address-of operator &b means I want to get the memory address of variable b * - dereference operator *c means I want to retrieve the value in address c
Memory model 1001 1002 1003 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 1 byte
Memory model 1001 1002 1003 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 1 byte = 8 bits off on A bit has 2 states
Memory model 1001 1002 1003 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 1 byte = 8 bits off on A bit has 2 states A byte has 256 (=2 8 ) states
Memory model 1001 1002 1003 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 1 byte = 8 bits off on A bit has 2 states A byte has 256 (=2 8 ) states A char takes 1 byte An int takes 4 bytes A double takes 8 bytes
Data type review Basic data types Type Bytes Bits Value range char 1 8-128 to 127 short 2 16-32,768 to 32,767 int 4 32-2,147,483,648 to 2,147,483,647 long long 8 64-9 * 10^18 to 9 * 10^18 float 4 32-3.4 * 10^38 to 3.4 * 10^38 double 8 64-1.7 * 10^308 to 1.7 * 10^308
Memory model 1001 1002 1003 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 1 byte = 8 bits off on A bit has 2 states A byte has 256 (=2 8 ) states My has 16GB ram
Memory model 1001 1002 1003 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 1 byte = 8 bits off on A bit has 2 states A byte has 256 (=2 8 ) states My has 16GB ram = 16,000,000,000 bytes!
What s going on in the memory 1001 1002 1003 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 int a = 5; int b = 3; double c = 3.5; int d = b - a;
What s going on in the memory a 5 int a = 5; int b = 3; double c = 3.5; int d = b - a; 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019
What s going on in the memory a 5 int a = 5; int b = 3; double c = 3.5; int d = b - a; b 3 1009 1010 1011 1013 1014 1015 1017 1018 1019
What s going on in the memory a 5 int a = 5; int b = 3; double c = 3.5; int d = b - a; b 3 c 3.5 1017 1018 1019
What s going on in the memory a 5 int a = 5; int b = 3; double c = 3.5; int d = b - a; b 3 c 3.5 d 2
What s going on in the memory 1001 1002 1003 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 int a = 5; int *b = &a; a++; *b += 2; cout << a << endl; cout << *b << endl;
What s going on in the memory a 5 int a = 5; int *b = &a; 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 a++; *b += 2; cout << a << endl; cout << *b << endl;
What s going on in the memory a 5 int a = 5; int *b = &a; 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 a++; *b += 2; cout << a << endl; cout << *b << endl;
What s going on in the memory a 5 int a = 5; int *b; b = &a; // declare a pointer var // set address 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 a++; *b += 2; cout << a << endl; cout << *b << endl;
What s going on in the memory a 5 int a = 5; int *b; b = &a; // declare a pointer var // set address a++; *b += 2; b?? (address) cout << a << endl; cout << *b << endl; 1013 1014 1015 1017 1018 1019
What s going on in the memory a 5 int a = 5; int *b; b = &a; // declare a pointer var // set address a++; *b += 2; b (address) cout << a << endl; cout << *b << endl; 1013 1014 1015 1017 1018 1019
What s going on in the memory a 5 à 6 int a = 5; int *b; b = &a; // declare a pointer var // set address a++; *b += 2; b (address) cout << a << endl; cout << *b << endl; 1013 1014 1015 1017 1018 1019
What s going on in the memory a 6 à 8 int a = 5; int *b; b = &a; // declare a pointer var // set address a++; *b += 2; b (address) cout << a << endl; cout << *b << endl; 1013 1014 1015 1017 1018 1019
What s going on in the memory a 8 int a = 5; int *b; b = &a; // declare a pointer var // set address a++; *b += 2; b (address) cout << a << endl; cout << *b << endl; 1013 1014 1015 1017 1018 1019 Output 8
What s going on in the memory a 8 int a = 5; int *b; b = &a; // declare a pointer var // set address a++; *b += 2; b (address) cout << a << endl; cout << *b << endl; 1013 1014 1015 1017 1018 1019 Output 8 8
Using uninitialized variables is always dangerous 1001 1002 1003 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 int a; int b = a + 3; int *c; *c = 27;
Using uninitialized variables is always dangerous a?? int a; int b = a + 3; int *c; 1005 1006 1007 1009 1010 1011 1013 1014 1015 1017 1018 1019 *c = 27;
Using uninitialized variables is always dangerous a?? int a; int b = a + 3; int *c; b?? *c = 27; 1009 1010 1011 1013 1014 1015 1017 1018 1019
Using uninitialized variables is always dangerous a?? int a; int b = a + 3; int *c; b?? *c = 27; c?? (address) 1017 1018 1019
Using uninitialized variables is always dangerous a?? int a; int b = a + 3; int *c; b?? *c = 27; c?? (address) May manipulate a piece of memory not belonging to this program!! 1017 1018 1019
Array v.s. Pointer Array is a special case of pointer Pointer can be treated as an array
Array in memory 1002 1006 1010 1014 1018 1020 1022 1024 1026 1028 1030 1032 1034 1036 1038 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = &b[1]; *c = 100;
Array in memory a 1006 3 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = &b[1]; 1010 *c = 100; 1014 1018 1020 1022 1024 1026 1028 1030 1032 1034 1036 1038
Array in memory a b[0] 3 10 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = &b[1]; b[1] 20 *c = 100; b b[2] b[3] 30 40 b[4] 1020 50 1024 1026 1028 1030 1032 1034 1036 1038
Array in memory a b[0] 3 10 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = &b[1]; b[1] 20 *c = 100; b b[2] b[3] 30 40 b[4] 1020 50 1024 1026 1028 1030 1032 1034 1036 1038
Array in memory b a b[0] b[1] b[2] b[3] 3 10 20 30 40 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c; // declare a pointer c = &b[1]; // get address *c = 100; b[4] 1020 50 1024 1026 1028 1030 1032 1034 1036 1038
Array in memory b a b[0] b[1] b[2] b[3] 3 10 20 30 40 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c; // declare a pointer c = &b[1]; // get address *c = 100; b[4] 1020 50 c 1024?? (address) 1032 1034 1036 1038
Array in memory b a b[0] b[1] b[2] b[3] 3 10 20 30 40 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c; // declare a pointer c = &b[1]; // get address *c = 100; b[4] 1020 50 c 1024 (address) 1032 1034 1036 1038
Array in memory b a b[0] b[1] b[2] b[3] 20 à 3 10 100 30 40 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c; // declare a pointer c = &b[1]; // get address *c = 100; b[4] 1020 50 c 1024 (address) 1032 1034 1036 1038
Time and Delta analogy Time + Delta = Time Delta + Delta = Delta Delta + Time = Time Time + Time = Doesn t make sense!
Time and Delta analogy + = + = + = + = Doesn t make sense!
Time and Delta analogy Pointer + Int = Pointer Int + Int = Int Int + Pointer = Pointer Pointer + Pointer = Doesn t make sense!
Time and Delta analogy Time - Delta = Time Delta - Delta = Delta Delta - Time = Doesn t make sense! Time - Time =??
Time and Delta analogy Time - Delta = Time Delta - Delta = Delta Delta - Time = Doesn t make sense! Time - Time = Delta
Time and Delta analogy - = - - - = = = Doesn t make sense!
Time and Delta analogy Pointer - Int = Pointer Int - Int = Int Int - Pointer = Doesn t make sense! Pointer - Pointer = Int
Array in memory a b[0] 3 10 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = &b[1]; b b[1] b[2] 20 30 c = c + 1; // Or, // c += 1; // c++; b[3] b[4] 1020 40 50 *c = 27; c 1024 (address) 1032 1034 1036 1038
Array in memory a b[0] 3 10 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = &b[1]; b b[1] b[2] 20 30 c = c + 1; // Or, // c += 1; // c++; b[3] b[4] 1020 40 50 *c = 27; c 1024 à (address) What? + 1 =? 1032 1034 1036 1038
Array in memory a b[0] 3 10 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = &b[1]; b b[1] b[2] 20 30 c = c + 1; // Or, // c += 1; // c++; b[3] 40 *c = 27; b[4] 1020 50 1024 c 1032 1034 à (address) Pointer arithmetic We should interpret as adding the memory size of 1 integer 1036 1038
Array in memory a b[0] 3 10 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = b; b b[1] b[2] b[3] 20 30 40 c += 2; *c = 27; b[4] 1020 50 Array name is a pointer c 1024 (address) b can be treated as an int* 1032 1034 1036 1038
Array in memory a b[0] 3 10 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = b; b b[1] b[2] b[3] 20 30 40 c += 2; *c = 27; b[4] 1020 50 Array name is a pointer c 1024 à (address) b can be treated as an int* 1032 1034 1036 1038
Array in memory a b[0] 3 10 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = b; b b[1] b[2] b[3] 30 à 20 27 40 c += 2; *c = 27; b[4] 1020 50 Array name is a pointer c 1024 (address) b can be treated as an int* 1032 1034 1036 1038
More about array Array name can be considered as start point Technically, it s the base address The index can be considered as the offset
More about array a 3 b[-4] b[-3] b[-2] b[-1] b[0] 10 b[0] b[1] 20 b[1] b b[2] 27 b[2] b[3] 40 b[3] b[4] c 1020 1024 1032 1034 1036 1038 50 (address) b[4] b[5] b[6] b[7] b[8] int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = b; cout << b[-1] << endl; b[9]
Use pointer like an array If x is a pointer, you can treat x as an array Meaning, you can have something like x[3]
Treat pointer as an array a 3 b[0] 10 b[1] 20 b b[2] b[3] b[4] 1020 27 40 50 int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = b + 2; c 1024 (address) cout << c[-2] << endl; 1032 1034 1036 1038
Treat pointer as an array a 3 b[0] 10 b[1] 20 b b[2] b[3] b[4] 1020 27 40 50 c[0] int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = b + 2; c 1024 (address) cout << c[-2] << endl; 1032 1034 1036 1038
Treat pointer as an array a 3 b[0] 10 b[1] 20 b b[2] b[3] b[4] 1020 27 40 50 c[0] c[1] c[2] int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = b + 2; c 1024 (address) c[3] c[4] cout << c[-2] << endl; 1032 1034 c[5] 1036 1038 c[6] c[7]
Treat pointer as an array a c[-4] 3 c[-6] c[-3] b[0] 10 c[-2] b[1] 20 c[-1] b b[2] b[3] b[4] 1020 27 40 50 c[0] c[1] c[2] int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = b + 2; c 1024 (address) c[3] c[4] cout << c[-2] << endl; 1032 1034 c[5] 1036 1038 c[6] c[7]
Treat pointer as an array a c[-4] 3 c[-6] c[-3] b[0] 10 c[-2] b[1] 20 c[-1] b b[2] b[3] b[4] 1020 27 40 50 c[0] c[1] c[2] int a = 3; int b[5] = {10, 20, 30, 40, 50; int *c = b + 2; c 1024 (address) c[3] c[4] cout << c[-2] << endl; 1032 1034 1036 1038 c[5] c[6] It is actually a valid memory access c[7]
Summary Array name is a pointer Pointer arithmetic Let s say x is a pointer, n is an integer x + n is a pointer (memory address) after n elements of x x - n is a pointer before n elements of x Treat a pointer as an array Again, let s say x is a pointer, n is an integer x[n] means to access n th element counted from x x[n] equivalent to *(x + n)
Remind a previous example 01 - Pass an array to a function From caller: In the function: int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10; foo(arr); or or void foo(int params[10]) { void foo(int params[]) { void foo(int *params) {
Remind a previous example 02 - Mapping of cipher and crib in project 5 Approach 3: Generate the mapping We first have a mapping array char cipher2crib[128] = { \0 ; Whenever we attempt to map lettera in cipher to letterb in crib: cipher2crib[lettera] = letterb; But there are only 26 letters. Why do we want to have an array with 128 elements? We use ascii as a key (a.k.a index) in the array We don t need to worry about the offset (i.e., x - a ) Is there any solution to reduce the size to 26?
Remind a previous example 02 - Mapping of cipher and crib in project 5 bool check(const char cipher[], const char crib[]) { // assume cipher and crib have the same length char cipher2crib[128] = {'\0'; for (int i = 0; cipher[i]!= '\0'; i++) { char lettera = cipher[i]; char letterb = crib[i]; if (cipher2crib[lettera]!= '\0 && cipher2crib[lettera]!= letterb) return false; cipher2crib[lettera] = letter return true;
Remind a previous example 02 - Mapping of cipher and crib in project 5 bool check(const char cipher[], const char crib[]) { // assume cipher and crib have the same length char truearray[26] = {'\0'; char *cipher2crib = truearray 'a'; for (int i = 0; cipher[i]!= '\0'; i++) { char lettera = cipher[i]; char letterb = crib[i]; if (cipher2crib[lettera]!= '\0 && cipher2crib[lettera]!= letterb) return false; cipher2crib[lettera] = letter return true; cipher2crib 97 elements truearray 26 elements Memory footprint
Question 01 If we declare int *ptr; and int val;, the following two usages are valid: ptr = &val; *ptr = val; What is &ptr?
Question 01 If we declare int *ptr; and int val;, the following two usages are valid: ptr = &val; *ptr = val; What is &ptr? &ptr means the address of ptr The type of &ptr is int** (we call it double pointer) For example, int** strongptr = &ptr;
Double pointer a 1006 3 int a = 3; int *b = &a; int c[5] = {10, 20, 30, 40, 50; int** d = &b; 1010 1014 1018 1020 1022 1024 1026 1028 1030 1032 1034 1036 1038
Double pointer a b 3 (address) int a = 3; int *b = &a; int c[5] = {10, 20, 30, 40, 50; int** d = &b; 1014 1018 1020 1022 1024 1026 1028 1030 1032 1034 1036 1038
Double pointer a b 3 (address) int a = 3; int *b = &a; int c[5] = {10, 20, 30, 40, 50; int** d = &b; c[0] 10 c[1] 20 c c[2] 1020 30 c[3] 1024 40 c[4] 1028 50 1032 1034 1036 1038
Double pointer a b 3 (address) int a = 3; int *b = &a; int c[5] = {10, 20, 30, 40, 50; int** d = &b; c[0] 10 c[1] 20 c c[2] 1020 30 c[3] 1024 40 c[4] 1028 50 d 1032 (address)
Question 02 If we declare int *ptr; and int val;, the following two usages are valid: ptr = &val; *ptr = val; What is *val?
Question 02 If we declare int *ptr; and int val;, the following two usages are valid: ptr = &val; *ptr = val; What is *val? It won t compile * operator (dereference) implies that what it stores is a memory address Only pointer variables store memory address
Different levels of pointers If we have Then they have the following relations int val; int* ptr1; int** ptr2; int*** ptr3; int**** ptr4; int***** ptr5; ptr5 = &ptr4; ptr4 = &ptr3; ptr3 = &ptr2; ptr4 = *ptr5; ptr3 = *ptr4; ptr2 = *ptr3; ptr2 = &ptr1; ptr1 = *ptr2; ptr1 = &val; of val = *ptr1; Deference
Question 03 If we declare int *ptr;, can we hardcode an address and assign to ptr? For example, ptr = 1234; No, it won t compile For security issue It doesn t make sense that we can get an address beforehand The same variable can reside in different parts of memory in different executions
Question 03 int a; cout << &a << endl;
Question 04 If we declare int *ptr; and double val;, is the following code valid? ptr = &val;
Question 04 If we declare int *ptr; and double val;, is the following code valid? ptr = &val; No, it won t compile Pointers are type-aware We can cast the type: ptr = (int*) &val; However, that means we use the way we interpret integer to intepret a piece of memory which stores a double
Array in memory a 3.5 double a = 3.5; int *b = (int*) &a; b (address) cout << *b << endl; 1018 1020 1022 1024 1026 1028 1030 1032 1034 1036 1038
Array in memory a 3.5 double a = 3.5; int *b = (int*) &a; b (address) cout << *b << endl; 1018 1020 1022 1024 1026 1028 1030 1032 1034 1036 1038
Question 05 If we declare int *ptri; and double *ptrd;, can we have the following assignment? ptri = ptrd; No, it won t compile Pointer type doesn t match Though both store memory addresses, how they interpret the memory content are different We can cast the type: ptri = (int*) ptrd;
Checkpoint Looping over the array Return a pointer double* findfirstnegativeptr(double a[], int n) { for (double* p = a; p < a + n; p++) { if (*p < 0) return p; return nullptr; Return an index int findfirstnegativeidx(double a[], int n) { for (int i = 0; i < n; i++) { if (a[i] < 0) return i; return -1;
Project 6 Problem 1b probably is the most tricky question.
Road map of CS31 String Array Function Class Variable If / else Loops Pointer!!
Class Define a data structure A data structure groups different variables together For example, when we describe a 2d coordinate, naturally we use 2 numbers to represent it We can also say we declare a new data type
Example // create a new data type class Point { public: double x; double y; ; // how we use it Point p; p.x = 1.1; p.y = 2.2; Point r = p; r.y = 3.3; cout << "Point 1: " << p.x << " " << p.y << endl; cout << "Point 2: " << r.x << " " << r.y << endl;