~~SLIDESHOW~~ ~~NOTOC~~ ====== Pointers 3 slides ====== Pointers, arrays, arithmetic.\\ Mithat Konar\\ October 23, 2021 ===== Pointers and arrays ===== * Arrays and pointers are closely related. * Array names are like a constant pointers: * the block of memory where an array name points cannot be changed, * what is stored there can change. ===== Pointers and arrays ===== The relationship is so close that you can use pointer operators with array names: int nums[] = {2, 4, 6, 8}; cout << nums[0] << endl; // prints 2 cout << nums << endl; // prints address where the array storage begins cout << *nums << endl; // prints 2 ===== Pointers and arrays ===== You can use array subscripting operations with pointers: int *myPtr = &nums[0]; // myPtr points to first element of nums cout << *myPtr << endl; // prints 2 cout << myPtr[0] << endl; // prints 2 cout << myPtr[1] << endl; // prints 4 cout << myPtr[2] << endl; // prints 6 ===== Pointers and arrays ===== The following are equivalent: int *myPtr = &nums[0]; // myPtr points to first element of nums int *myPtr = &*nums; // myPtr points to first element of nums int *myPtr = nums; // myPtr points to first element of nums ===== Pointer arithmetic ===== * Pointer arithmetic works differently than normal arithmetic. * ''+'', ''+='', ''-'', ''-='', ''++'', ''--'' do math in terms of the size of the pointed data type. * E.g., adding 1 to a pointer makes it point to the next block of memory corresponding to the size of the underlying type. /** Pointer arithmetic. */ #include using namespace std; int main() { int v[] = {2, 4, 6, 8, 12}; int *vPtr = v; cout << *vPtr << endl; // prints 2 vPtr = vPtr + 3; // vPtr now points to address vPtr + 3*sizeof(int), // i.e., v[3] cout << *vPtr << endl; // prints v[3] vPtr--; // vPtr now points to address vPtr - 1*sizeof(int), // i.e., v[2] cout << *vPtr << endl; // prints v[2] cout << *(vPtr + 2) << endl; // prints v[4] return 0; } ===== Pointer arithmetic: pointer difference ===== Subtracting one pointer from another returns the number of elements between two addresses: /** Subtracting pointers */ #include using namespace std; int main() { int v[] = {2, 4, 6, 8, 12, 0}; int *vPtr = &v[0]; int *vPtr2 = &v[3]; cout << vPtr2 - vPtr << endl; // prints 3 return 0; } ===== Walking down an array ===== A common technique used to visit every element in an array is to //walk down an array// with a pointer: /** Walking down an array. */ #include using namespace std; int main() { int v[] = {2, 4, 6, 8, 12}; int *vPtr = v; for (int i = 0; i < 5; i++) { cout << *vPtr << endl; vPtr++; } return 0; } Especially common with zero-terminated (i.e., NULL terminated) partially-filled arrays: /** Walking down a null-terminated array. */ #include using namespace std; int main() { int v[20] = {2, 4, 6, 8, 12}; int *vPtr = v; while (*vPtr != 0) { cout << *vPtr << endl; vPtr++; } return 0; } ===== Summary ===== The following examples below assume: int vals[] = {4, 7, 11}; int *valptr = vals; ===== Array access techniques ===== ^ Access technique ^ Example ^ | ''arrayName[N]'' |vals[2] = 17; | | ''pointerName[N]'' |valptr[2] = 17; | | ''arrayName'' and subscript arithmetic |*(vals + 2) = 17; | | ''pointerName'' and subscript arithmetic |*(valptr + 2) = 17; | ===== Array arithmetic ===== ^ Operation ^ Example ^ |pointer++ |valptr++; // points at 7 | |pointer-- |valptr--; // now points at 4 | |pointer + int |cout << *(valptr + 2); // prints 11 | |pointer += int |valptr = vals; // points at 4 valptr += 2; // points at 11 | |pointer - pointer |cout << valptr - vals; // # of ints between valptr and vals |