200 likes | 314 Vues
This document provides an in-depth review of C-strings and 2D arrays, essential components in C programming. C-strings are defined as character arrays ending with a null terminator, and the <cstring> library offers various functions for their manipulation. The section on 2D arrays explains their structure, including row and column conventions, and how to declare and manipulate them. Additional insights into variable storage, addressing, pointers, and array access enhance understanding. This review supports fundamental programming concepts crucial for efficient coding in C.
E N D
CS 31 Discussion, Week 7 Faisal Alquaddoomi, faisal@cs.ucla.edu Office Hours: BH 2432, W 4:30-6:30pm,F 12:30-1:30pm
C-Strings Review • C-Strings are just char arrays, with some convenient functions for manipulating them • End in a ‘nul-terminator’ that signifies the end of the string • C-Strings have special manipulation functions in the <cstring> library
2D Arrays Review • 2D arrays are like 1D arrays, except they have an extra dimension • by convention, the first dimension is the row, the second is the column • declare:intmyArray[5][10]; // 5 rows, 10 columns • access/change:myArray[2][3] = 888; // ^ item at row 2, col 3 is now 888 • 2D arrays can be statically allocated, but the second dimension (columns) must be specified • Similarly, when writing a function that takes a 2D array as a parameter, the second dimension must also be specified:void myFunc(char inArray[][5]) { /* body of function here… */ }
Notes on Project 5 • Just like any other type, you can have 2D arrays of C-strings, e.g.char doc[50][81]; // 50 lines, 80 chars + ‘\0’ each • Reading lines from istream is the same as from cin • Here’s a way to read 50 lines from an istream& (say, ‘mystream’):int lines = 0; while (lines < 50 && mystream.getline(doc[lines++],80)) continue;
Variables Revisited • Variables have a type, a name, and a value • Arrays are extensions of this idea • We can pass variables “by value” to functions, which causes their contents to be copied • We can also pass “by reference”, which changes the original variable when the reference changes • Arrays are always passed by reference…but why?
How Variables Are Stored int main() { int x; int y = 2; char c; double d; int q[5] = { 1, 2, 3 }; x = 3; c = ‘H’; d = 3.5; cout << “x: ” << x << endl; return 0; }
How Variables Are Stored int main() { int x; int y = 2; char c; double d; int q[5] = { 1, 2, 3 }; x = 3; c = ‘H’; d = 3.5; cout<< “x: ” << x << endl; return 0; } x y c d q[0] q[1] q[2] q[3] q[4] name: 3 2 ‘H’ 3.5 1 2 3 ? ? value:
Variable Storage, Scaled to Size x y c d name: 3 2 H 3.5 value: q[0] q[1] q[2] q[3] q[4] name: 1 2 3 ? ? value: 4 bytes
One More Attribute for Variables • In addition to a type, a name, and a value, variables also have an address • Just like the address of a house, it specifies where to find that variable in memory • Arrays are kind of like apartments, where each slot specifies a different place, all starting from the same address q @ 12 to 32 y @ 4 x @ 0 z @ 8 …
Variables with Addresses x y c d name: 3 2 H 3.5 value: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 q[0] q[1] q[2] q[3] q[4] name: 1 2 3 ? ? value: 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 .. 4 bytes
Operations on Addresses • From the previous example: • x has address 0, y has address 4, c has address 8, d is at 9 • q starts @17 and has slots @17, 21, 25, 29, and 33 • Retrieve the address of a variable/array using the ‘&’ operator, e.g.:cout<< (&x); // might print ‘0’ • Get the value at an address using the ‘*’ operator, e.g.:cout<< *(&x); // would print 3
Storing an Address, “Pointers” • Even though addresses are just numbers, they are very often stored in a special family of types • called the “pointer types”; an instance of this type is a “pointer” • For instance, the address of an int can be stored in a pointer type called int*, read as “pointer to int” • one pointer type per regular type, e.g. int has “int*”, char has “char*”, etc. • There’s a special pointer type called “void*”, but we’ll get to that later…
Creating and Assigning a Pointer • Assuming the previous code, this creates a pointer to ‘x’ and manipulates it a bit:// stores address of x in pxint* px = &x; // prints address of xcout << (int)(px) << endl; // changes x to 32 *(px) = 32; x y c d px name: 3 2 ‘H’ 3.5 0 … value:
Pointers to Arrays (and Pointer Arithmetic) • There is no difference between a pointer to a variable and a pointer to an array • …but this is where the type of the pointer starts to become useful • Set ‘pq’ to point to our ‘q’ array:int* pq = q; // q was already a pointer! // …q[0] is the value of the first element • Move ‘pq’ to the next element in ‘q’:pq = pq + 1; // moves pq 4b forward • ‘pq’ moves forward by 4 bytes because it’s a pointer to int, which is of size 4 • if it were a pointer to char, we’d move forward 1 byte and be in the middle of the first element rather than at the second element
Array Access Revisited • As established, ‘q’ is actually a pointer that points to the first element in its array • This is why we’ve had to pass the length of an array around all the time, because all ‘q’ knows is that it starts at some place and has a type • ‘q’s value tells it where to start, and its type tells it how to get to a particular element’s offset • (e.g. by multiplying size of type and desired element position, then adding it to the address of the first element, which is ‘q’) • The operator q[x] is actually *(q + size of type * index), e.g.: // let’s get the third element, slot 2cout << *(q + 4*2); // 4 == size of intin bytes // gets the value of the element // starting at q, then shifted over ‘x’ // units of the type’s size
Passing by Reference Revisited • The ‘reference’ that’s passed to a function is actually the address of the variable • C++ is doing you some confusing ‘favors’, like using ‘&’ on the argument and implicitly using ‘*’ every time the reference is mentioned • added to the language because passing pointers is so common
Passing by Reference, Part 2 • This code:void p(int& x) { x = 32; }int main() {int a; p(a);cout << a; /*etc*/ } • …is (almost) equivalent to this code:void p(int* x) { *x = 32; }intmain() {int a;p(&a);cout<< a;/*etc*/ }
Addresses and Pointers Review • All variables have an address in memory (as well as an amount of space they consume dictated by their type) • The address can be retrieved via the ‘&’ operator • The value at an address can be retrieved/changed using the ‘*’ operator on an address
Addresses and Pointers Review, Part 2 • A pointer is a special type used for holding addresses • Pointers can be manipulated using +, -, which moves them in ‘steps’ of their type’s size, e.g.:int* p; p = p + 3;// moves p (3*4) = 12 bytes forward in memory • Arrays are actually pointers to the first element • The subscript operator [] is implemented using pointer arithmetic; assuming q is an array of ints:q[x] == *(q+4*x)