Presentation is loading. Please wait.

Presentation is loading. Please wait.

Pointer arithmetic.

Similar presentations


Presentation on theme: "Pointer arithmetic."— Presentation transcript:

1 Pointer arithmetic

2 Outline In this lesson, we will:
Review that pointers store addresses of specific types See that we can add integers to addresses The result depends on the type See that you can also take differences of pointers Again, the result depends on the type

3 Pointer arithmetic Recall that: It makes no sense to add two addresses
Pointers are addresses Addresses are positive integers It makes no sense to add two addresses int *p_value_1{new int{42}}; int *p_value_2{new int{91}}; std::cout << (p_value_1 + p_value_2) << std::endl; It’s like asking “What address is 111 Wellington St + 24 Sussex Dr?”

4 Pointer arithmetic You can, however, ask “What is the next address?”
However, the next address isn’t always the next chronologically What address follows 24 Sussex Dr.? The French Embassy at 42 Sussex Dr. What address comes two before 24 Sussex Dr.? The South African High Commission at 15 Sussex Dr.

5 Pointer arithmetic You can, however, ask “What is the next address?”
However, the next address isn’t always the next chronologically What address follows 24 Sussex Dr? The French Embassy at 42 Sussex Dr 25 Sussex Dr does not exist What address comes two before 24 Sussex Dr? The South African High Commission at 15 Sussex Dr

6 Pointer arithmetic Suppose you have an array:
int *a_data{new int[20]{}}; std::cout << a_data << std::endl; Suppose that 'a_data' is assigned 0x93a3d0 Question: What is the value of a_data + 1?

7 Next address Let’s try it out: Output a_ray == 0x1fb1010
#include <iostream> int main(); int main() { int *a_ray{new int[10]}; std::cout << "a_ray == " << a_ray << std::endl; std::cout << "a_ray + 1 == " << (a_ray + 1) << std::endl; delete[] a_ray; a_ray = nullptr; return 0; } Output a_ray == 0x1fb1010 a_ray + 1 == 0x1fb1014

8 Next address Let’s try it with an array of double: Output
#include <iostream> int main(); int main() { double *a_ray{new double[10]}; std::cout << "a_ray == " << a_ray << std::endl; std::cout << "a_ray + 1 == " << (a_ray + 1) << std::endl; delete[] a_ray; a_ray = nullptr; return 0; } Output a_ray == 0x1af7010 a_ray + 1 == 0x1af7018

9 Next address Recall that an int occupies 4 bytes, while a double occupies 8 bytes The compiler says: a_ray is the address of a double, so the next double is 8 bytes after the current address…

10 The kth address We can even walk though an array: Output
#include <iostream> int main(); int main() { double *a_ray{new double[6]{0, 1, 2, 3, 4, 42}}; for ( std::size_t k{0}; k < 6; ++k ) { std::cout << (a_ray + k) << " stores the value " << *(a_ray + k) << std::endl; } delete[] a_ray; a_ray = nullptr; return 0; Output 0x1af0010 stores the value 0 0x1af0018 stores the value 1 0x1af0020 stores the value 2 0x1af0028 stores the value 3 0x1af0030 stores the value 4 0x1af0038 stores the value 42

11 Array entries The following two statements are equivalent:
a_ray[k] *(a_ray + k) The first says: Access the kth entry of the array a_ray The second says: Find the address of k entries beyond a_ray and access that address In general, the first is much easier to read

12 Array entries The following two statements are also equivalent:
&( a_ray[k] ) a_ray + k The first says: Find the address of the kth entry of the array a_ray The second says: Find the address of k entries beyond a_ray In this case, the second is easier to read!

13 Array entries Now you understand why all arrays in C++ start at index 0 a_ray[0] == *(a_ray + 0) and *(a_ray + 0) == *a_ray The decision to start array indices at 0 was entirely practical

14 Walking through arrays
We can walk through arrays: #include <iostream> int main(); int main() { int *a_ray{new int[6]{0, 1, 2, 3, 4, 42}}; for ( int *p_ray{a_ray}; p_ray < a_ray + 6; ++p_ray ) { std::cout << p_ray << " stores the value " << *p_ray << std::endl; } delete[] a_ray; a_ray = nullptr; return 0; Increment 'p_ray' to the next valid address of an int Output 0x183a010 stores the value 0 0x183a014 stores the value 1 0x183a018 stores the value 2 0x183a01c stores the value 3 0x183a020 stores the value 4 0x183a024 stores the value 42

15 Walking through arrays
Question: Should you, or should you not delete p_ray? Why? #include <iostream> int main(); int main() { int *a_ray{new int[6]{0, 1, 2, 3, 4, 42}}; for ( int *p_ray{a_ray}; p_ray < a_ray + 6; ++p_ray ) { std::cout << p_ray << " stores the value " << *p_ray << std::endl; } delete[] a_ray; a_ray = nullptr; return 0;

16 Pointer differences Remember, it makes no sense to ask
“What is 111 Wellington St + 24 Sussex Dr?” On the other hand… 1100 S Ocean Blvd Pennsylvania Avenue NW = &hell You might ask, however, “How many buildings away is Sir Winston Churchill Secondary School from Denis Morris Catholic High School?” Given the addresses 101 Glen Morris Dr and 40 Glen Morris Dr: The wrong answer is 61… The right answer is 3

17 Pointer differences Similarly, we may ask about a difference of addresses: #include <iostream> int main(); int main() { double *a_ray{new double[6]{0, 1, 2, 3, 4, 42}}; double *p_1{&(a_ray[2])}; double *p_2{&(a_ray[5])}; std::cout << p_1 << " " << p_2 << std::endl; std::cout << (p_1 - p_2) << std::endl; std::cout << (p_2 - p_1) << std::endl; delete[] a_ray; a_ray = nullptr; return 0; } Output 0xd xd02038 -3 3

18 Pointer differences Question: What is the type of a pointer difference? Remember that pointers are addresses The type std::size_t depends on the address size This type is unsigned—addresses are unsigned A reasonable approximation would be a signed equivalent of std::size_t Such a type is defined: std::ptrdiff_t Literally, a pointer-difference type This is unique for operators: the return type is different from the types of the operands Not a problem, a function can have a return type that is different from its arguments, too

19 Pointer differences Question: What is the type of a pointer difference? #include <iostream> int main(); int main() { double *a_ray{new double[6]{0, 1, 2, 3, 4, 42}}; double *p_1{&(a_ray[2])}; double *p_2{&(a_ray[5])}; std::ptrdiff_t diff = p_1 - p_2; std::cout << diff << std::endl; delete[] a_ray; a_ray = nullptr; return 0; } Output -3

20 Pointer differences The memory occupied by a pointer, std::size_t and std::ptrdiff_t are all the same: #include <iostream> int main(); int main() { std::cout << sizeof( int * ) << std::endl; std::cout << sizeof( std::size_t ) << std::endl; std::cout << sizeof( std::ptrdiff_t ) << std::endl; return 0; } Output on ecelinux: 8

21 Summary Following this lesson, you now
Know that integers can be added to addresses and the difference depends on the type Understand that array[k] and *(array + k) are equivalent The first, however, is clearer to read Know that we can calculate the difference between addresses

22 References [1] No references?

23 Colophon These slides were prepared using the Georgia typeface. Mathematical equations use Times New Roman, and source code is presented using Consolas. The photographs of lilacs in bloom appearing on the title slide and accenting the top of each other slide were taken at the Royal Botanical Gardens on May 27, 2018 by Douglas Wilhelm Harder. Please see for more information.

24 Disclaimer These slides are provided for the ece 150 Fundamentals of Programming course taught at the University of Waterloo. The material in it reflects the authors’ best judgment in light of the information available to them at the time of preparation. Any reliance on these course slides by any party for any other purpose are the responsibility of such parties. The authors accept no responsibility for damages, if any, suffered by any party as a result of decisions made or actions based on these course slides for any other purpose than that for which it was intended.


Download ppt "Pointer arithmetic."

Similar presentations


Ads by Google