General Talk on Pointers


Published on

Published in: Technology, Education
1 Like
  • Be the first to comment

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

General Talk on Pointers

  1. 1. General Talk on Pointers and memory
  2. 2. Ch. 17.3 <ul><li>section 17.3  </li></ul><ul><li>This is difficult reading.  </li></ul><ul><li>Try to read it with pencil and paper,  to one side of your laptop or computer at RCC! </li></ul>
  3. 3. memory in your computer <ul><li>When you buy a computer, you know that you need to buy a certain amount of RAM, and that it's measured in (big) integers. </li></ul><ul><li>When you buy a hard drive, whether internal, external or flash, </li></ul><ul><li>you also measure the size in (big) integers. </li></ul><ul><li>Your flash drive may be 1G. What exactly is that 1 G? </li></ul><ul><li>It's one gigabyte: a billion bytes. </li></ul><ul><li>Think of your computer's memory as a long chain of bytes. </li></ul>
  4. 4. memory in your computer    <ul><li>Thinking of that long stream of bytes: </li></ul><ul><li>Imagine that the bytes are numbered  </li></ul><ul><li>from 0 through 1G on that flash drive,  </li></ul><ul><li>or in RAM from 0 through 24 GB  </li></ul>
  5. 5. Declare a variable <ul><li>int myInt = 999; </li></ul><ul><li>Somewhere in memory, there is an int sized piece set aside </li></ul><ul><li>1) with the handle &quot;myInt&quot; </li></ul><ul><li>2) with the contents 999 </li></ul><ul><li>The computer has no idea of the variable name myInt. </li></ul><ul><li>myInt is just a fiction that the compiler provides for you. </li></ul><ul><li>The computer represents that place as address #FFF780 </li></ul><ul><li>(in hexadecimal). </li></ul><ul><li>Memory is numbered. The addresses are the numbers. </li></ul>
  6. 6. Addresses to Places in memory <ul><li>You can refer to that variable as myInt, the handle that you assigned to it. </li></ul><ul><li>Or you can refer to that variable in a more abstract way,  </li></ul><ul><li>via its address in memory, </li></ul><ul><li>NEW SYNTAX: </li></ul><ul><li>   int * myIntPtr = & myInt; </li></ul><ul><li>what? What? WHAT? </li></ul>
  7. 7.   int  *  myIntPtr =  & myInt; <ul><li>Let's dissect the pieces. </li></ul><ul><li>& myInt </li></ul><ul><li>  </li></ul><ul><li>We have already seen similar in the stream example. </li></ul><ul><li>& means &quot;address of &quot; </li></ul><ul><li>All variables have an address in memory. </li></ul><ul><li>The & operator takes the address of a variable. </li></ul><ul><li>&myInt means, the address to where the myInt label refers. </li></ul>
  8. 8.   int  *  myIntPtr =  & myInt; <ul><li>More pieces: </li></ul><ul><li>int  *  myIntPtr </li></ul><ul><li>This is a variable declaration, similar to the int declaration. </li></ul><ul><li>But it does not declare an int, it declares a pointer to an int. </li></ul><ul><li>myIntPtr is a variable that does not itself contain an int. It contains an address, where an int resides. </li></ul>
  9. 9.   int  *  myIntPtr =  & myInt; <ul><li>Analogy: </li></ul><ul><li>You live in your house or apartment. </li></ul><ul><li>You have moved from elsewhere, and have address forwarding.  </li></ul><ul><li>The post office has a catalog of where all forwarded mail should go. </li></ul><ul><li>You get a piece of mail, via your old post office. </li></ul><ul><li>The post man sees your name, and looks up a reference to your new address. </li></ul><ul><li>1) You are the number 17. </li></ul><ul><li>2) Your house is the int myInt. </li></ul><ul><li>3) The reference at the old post office is the pointer, myIntPtr. </li></ul>
  10. 10.   int  *  myIntPtr =  & myInt; <ul><li>say that myInt is at address #FFF880 (or whevs) </li></ul><ul><li>myInt = 17; </li></ul><ul><li>int  *  myIntPtr =  & myInt; </li></ul><ul><li>Now the value 17 is in myInt,  </li></ul><ul><li>and the value FF880 is in myIntPtr. </li></ul>
  11. 11. Dereferencing a Pointer <ul><li>Doing what to a pointer now? </li></ul><ul><li>Say that you are not aware of the myInt variable. </li></ul><ul><li>Say that your code is only aware of the myIntPtr variable. </li></ul><ul><li>Remember: </li></ul><ul><li>myInt = 17; </li></ul><ul><li>  int  *  myIntPtr =  & myInt; </li></ul><ul><li>how do you get at that 17 via myIntPtr? </li></ul><ul><li>NEW SYNTAX </li></ul><ul><li>int myOtherInt = * myIntPtr; </li></ul><ul><li>&quot;*variable name&quot; is read as &quot;the contents of variable name&quot; </li></ul>
  12. 12. Derefencing Examples <ul><li>Dereference on the Left </li></ul><ul><li>int * ptr1; </li></ul><ul><li>char * ptr2; </li></ul><ul><li>*ptr1 = 888; </li></ul><ul><li>The contents of ptr1 gets 888 </li></ul><ul><li>*ptr2 = 'c'; </li></ul><ul><li>The contents of ptr2 gets 'c' </li></ul><ul><li>Dereference on the Right </li></ul><ul><li>int * ptr1; </li></ul><ul><li>char * ptr2; </li></ul><ul><li>int anInt; </li></ul><ul><li>char aChar; </li></ul><ul><li>anInt = *ptr1; </li></ul><ul><li>anInt gets the contents of ptr1 </li></ul><ul><li>aChar = *ptr2; </li></ul><ul><li>aChar gets the contents of ptr2 </li></ul>
  13. 13. Pointers to a thing  are not the same   as the thing <ul><li>So you can't mix and match. </li></ul><ul><li>You will have errors around this issue.  </li></ul><ul><li>int  *  myIntPtr =  & myInt; </li></ul><ul><li>int anotherInt = myIntPtr;  </li></ul><ul><li>// not legal </li></ul><ul><li>char * myCharPtr = &myChar; </li></ul><ul><li>char anotherChar = myCharPtr; </li></ul><ul><li>// again, not legal </li></ul>
  14. 14. sizeof     <ul><li>This little funtion (or operator) tells you how much space a given thing takes up in memory. </li></ul><ul><li>You can find out interesting details about the architecture of your machine using sizeof. </li></ul>
  15. 15. sizeof <ul><li>Guesses (and thoughts) from the students please: </li></ul><ul><li>How big is an int? sizeof(int) </li></ul><ul><li>How big is a char? sizeof(char) </li></ul><ul><li>How big is a pointer to an int? sizeof(int*) </li></ul><ul><li>How big is a pointer to a char? sizeof(char*) </li></ul><ul><li>How big is a literal? sizeof('a') </li></ul><ul><li>another literal? sizeof(999) </li></ul><ul><li>another literal? sizeof(&quot;blablblalba&quot;) </li></ul><ul><li>How big is a boolean? </li></ul><ul><li>How big is a double? </li></ul><ul><li>How big is an empty vector? </li></ul><ul><li>How big is a vector with entries? </li></ul>
  16. 16. The Null Pointer    <ul><li>How do you initialize a pointer? </li></ul><ul><li>You set it to null, which is 0; </li></ul><ul><li>int * myIntPtr = 0; </li></ul><ul><li>Sometimes people test a pointer before using it: </li></ul><ul><li>if (myIntPtr) </li></ul><ul><li>{ </li></ul><ul><li>   // do some code if the pointer contains a value other than 0 </li></ul><ul><li>} </li></ul><ul><li>else </li></ul><ul><li>{ </li></ul><ul><li>// do some other code for the case when myIntPtr is empty </li></ul><ul><li>} </li></ul>
  17. 17. The Null Pointer <ul><li>It's also valid to test for the null pointer like this: </li></ul><ul><li>if (myIntPtr != 0) </li></ul><ul><li>{ </li></ul><ul><li>// there is a value in there, do something </li></ul><ul><li>} </li></ul><ul><li>else </li></ul><ul><li>{ </li></ul><ul><li>// there's not a value in there, do something else </li></ul><ul><li>} </li></ul>
  18. 18. Testing for the Null Pointer <ul><li>It's not 100% fool-proof to test for the null pointer. </li></ul><ul><li>1) There could be junk in the variable. When you test it, it's not 0, but it's not a valid pointer value either. </li></ul><ul><li>This happens when variables are not initialized or when they are mistakenly overwritten. </li></ul><ul><li>2) The pointer could be pointing to an object that has been deleted, or garbage collected. </li></ul><ul><li>WHAT? ARE? YOU? TALKING? ABOUT? The Heap. </li></ul><ul><li>More next lecture. Difficult topics ahead! </li></ul>
  19. 19. What happens when you  declare a variable? <ul><li>When you declare some variables,  </li></ul><ul><li>whether in or outside of main, </li></ul><ul><li>the compiler knows what space you will need, </li></ul><ul><li>at compile time. </li></ul><ul><li>int oneInt, twoInt, threeInt; </li></ul><ul><li>int main() </li></ul><ul><li>{ </li></ul><ul><li>char oneChar, twoChar, threeChar; </li></ul><ul><li>... </li></ul><ul><li>} </li></ul><ul><li>How much space do we need for variables? Please calculate. </li></ul>
  20. 20. Industrial Applications <ul><li>Say you write a program to manage bank records. </li></ul><ul><li>Do you know ahead of time how many records you will need? </li></ul><ul><li>What can you do to get around this problem? </li></ul><ul><li>  </li></ul><ul><li>1) Declare an arbitrary upper limit. If the bank needs more records than that, well, tough nougies. </li></ul><ul><li>2) Create an insanely large number of records to start. If you don't use that space for records, use it up anyway &quot;just in case&quot;. </li></ul><ul><li>Easy question:  </li></ul><ul><li>Can you point out the problem with these solutions? </li></ul>
  21. 21. Solution: Dynamic allocation of Memory <ul><li>Dynamic in this context means: </li></ul><ul><li>marked by usually continuous and productive activity or change </li></ul><ul><li>  </li></ul><ul><li>Allocation in this context means: </li></ul><ul><li>the act of distributing by allotting or apportioning;  </li></ul><ul><li>distribution according to a plan;  </li></ul><ul><li>Meaning what? That the amount of space your program uses is not determined at compile time, but at run time. </li></ul><ul><li>Please define again the difference between  </li></ul><ul><li>compile time and run time. </li></ul>
  22. 22. Dynamic Allocation of Memory <ul><li>The system provides you with mechanisms to conditionally ask for more memory as you need it and use it. </li></ul><ul><li>You have already used some of these mechanisms. </li></ul><ul><li>What do you think happens when you type: </li></ul><ul><li>anyVector.push_back(anyValue)? </li></ul>
  23. 23. What happens when you  create a new object? <ul><li>You have seen problems where we create new objects.  </li></ul><ul><li>You yourself programmed them in the library-book assignment. </li></ul><ul><li>Can you think of a case of dynamic allocation of memory from that project? </li></ul>
  24. 24. A little bit of Architecture <ul><li>Memory is just a long list of bytes, addressable by pointers. </li></ul><ul><li>But most operating systems divide up that memory according to some orderly scheme. Here's one such scheme. </li></ul><ul><li>1) Some memory corresponds to the code that you wrote, the instructions. These are the functions and main. </li></ul><ul><li>2) Some is for the variables you have declared outside of main. </li></ul><ul><li>3) Some is for the variables you have declared in the functions, including main. </li></ul><ul><li>4) The rest of the memory is free for other uses </li></ul>
  25. 25. A little bit of Architecture <ul><li>The four pieces are called: </li></ul><ul><li>  </li></ul><ul><li>code </li></ul><ul><li>static </li></ul><ul><li>the stack </li></ul><ul><li>the heap </li></ul>
  26. 26. How to allocate the code portion? <ul><li>You do this when you write your code. </li></ul><ul><li>But remember it's translated into machine language. </li></ul><ul><li>Your files are called source files. Your comments won't make it into the code! </li></ul><ul><li>The code portion is fixed at the outset. </li></ul>
  27. 27. How to allocate the static portion? <ul><li>Again, you do this when you write your code.  </li></ul><ul><li>  </li></ul><ul><li>These are all the variables that you define outside of main,  </li></ul><ul><li>and the variables that you define in your .h files. </li></ul><ul><li>These are called static , as a group, because they will not change in size, although they may change in contents. </li></ul><ul><li>These are called the global variables, because they are visible to all the functions in a file.  </li></ul><ul><li>With some exceptions. Remember how we declared them in different places in a file and affected visibility.  </li></ul>
  28. 28. How to allocate the stack portion? <ul><li>When you write your code, you tell the compiler what variables a particular function (including main) wants to use. </li></ul><ul><li>When your function is invoked (run) ,  </li></ul><ul><li>that's when space for those variables is set aside,  </li></ul><ul><li>on the stack. </li></ul>
  29. 29. The Stack : some more detail <ul><li>Let's consider the example of the function that had a vector as a parameter, and that swapped the words in that vector. </li></ul><ul><li>  </li></ul><ul><li>When we were calling the function with the vector by value,  </li></ul><ul><li>our changes to that vector were no longer in effect  </li></ul><ul><li>when we returned from the function. </li></ul><ul><li>  </li></ul><ul><li>  Why did this happen? Because when you call by value, you get a copy of the parameters in the destination function, not the originals. </li></ul><ul><li>What do I mean by &quot;in&quot; the destination function? Where is that? </li></ul>
  30. 30. Why is it called a stack? <ul><li>It's like a stack of dishes.  </li></ul><ul><li>You should take a dish off the top of the stack, </li></ul><ul><li>and place a dish on the top of the stack. </li></ul><ul><li>Your program starts in tmain, and it calls a function, </li></ul><ul><li>process_file. </li></ul><ul><li>Process_file calls a function,  </li></ul><ul><li>process_line. </li></ul><ul><li>process_line </li></ul><ul><li>process_file </li></ul><ul><li>_tmain </li></ul>
  31. 31. Stack example: vectors <ul><li>You have been using the vector class for weeks now. </li></ul><ul><li>Many have been using the push_back function. The opposite of the push_back function is the pop_back function. </li></ul><ul><li>What does the word back refer to in both cases?  </li></ul><ul><li>Knowing what push means, what do you think </li></ul><ul><li>pop must mean? </li></ul><ul><li>Thoughts from the class. </li></ul>
  32. 32. One stack operation on a vector <ul><li>You can imagine something like this happening to your vector. </li></ul>
  33. 33. Functions on a Stack <ul><li>Now apply that same concept to your functions. </li></ul><ul><li>The computer keeps track of them all in a stack. </li></ul><ul><li>The bottom of the stack is an object that represents tmain. It has a stack &quot;frame&quot;. The stack frame is like one entry in a vector. In the stack frame you have room for all the variables declared in tmain. </li></ul><ul><li>Say tmain calls process_file.  process_file gets a stack frame that sits on top of tmain's stack frame, just like in the stack of dishes, or in a vector. That frame has process_file's variables. Those are the only local variables visible to the stack frame.  </li></ul><ul><li>Local variables are those that are in the current stack frame. </li></ul><ul><li>Only the variables in the current frame are visible! Other than global variables. </li></ul>
  34. 34. Local Variables in the Stack Frame <ul><li>Think of the functions all piled up in a stack,  </li></ul><ul><li>in the order in which they are called. </li></ul><ul><li>Only local variables are visible: </li></ul><ul><li>They are the ones in the current stack frame. The &quot;top&quot;. </li></ul><ul><li>If you put those two thoughts together, you can see why in last week's examples with functions and call by value, no permanent changes are made to the parameters: </li></ul><ul><li>Because the parameters are  </li></ul><ul><li>copied into the new stack frame! </li></ul>
  35. 35. Stack of Dishes Analogy <ul><li>Look down at a stack of dishes,  </li></ul><ul><li>pilled up high, </li></ul><ul><li>each with some food on the plate. </li></ul><ul><li>You can only see the food on the top plate. </li></ul><ul><li>The food on the other plates  is not accessible to you. </li></ul><ul><li>That top dish is like the current stack frame. </li></ul><ul><li>The variables in a function are like the food on the plate. </li></ul><ul><li>You can only see and access the top dish! </li></ul>
  36. 36. At the end of a Function <ul><li>Each function has its own sandbox. Variables are copied into its sandbox.  </li></ul><ul><li>When the function is done, the stack is popped. Take away that plate and wash it. </li></ul><ul><li>All the info from that sandbox is gone. All that food is tossed. </li></ul><ul><li>The only thing that comes back is the return code, if you have one.  </li></ul><ul><li>The current stack frame is the old previous. That's the dish that was underneath, with the food on that plate. That function resumes where it left off. </li></ul>
  37. 37. The function's stack frame is gone <ul><li>All the variables from that ended frame go away. The previous stack frame, the one for the function that made the initial call, </li></ul><ul><li>is the new current stack frame. </li></ul><ul><li>But remember, what do we do if we either </li></ul><ul><li>1) Don't want to copy everything into a new sandbox </li></ul><ul><li>-and/or- </li></ul><ul><li>2) Want some permanent change? </li></ul><ul><li>We use call by reference: POINTERS </li></ul>
  38. 38. call by Reference: Pointers <ul><li>If we use call by reference as we did in last week's examples  , then a pointer gets copied to the local stack frame </li></ul><ul><li>when a function is called. </li></ul><ul><li>The function, operating on a pointer,  </li></ul><ul><li>makes changes to the contents at the pointer . That may be elsewhere in the stack or somewhere else altogether. </li></ul><ul><li>When the stack frame is popped,  </li></ul><ul><li>the sandbox with the copy of the pointer goes away. </li></ul><ul><li>Changes made to the contents at the pointer  </li></ul><ul><li>are still in effect, if it wasn't an address in that stack frame! </li></ul>
  39. 39. Code , Static and Stack <ul><li>So far we have discussed three different ways that the computer will allocate memory to your program. </li></ul><ul><li>Let's return to a big industrial case. </li></ul><ul><li>A bank has many many functions that operate on its many records to maintain all of its many transactions. </li></ul><ul><li>These many records cannot be : </li></ul><ul><li>copied among functions (too much space, too slow) </li></ul><ul><li>changed over and over in each function, since call by argument changes are local (changes must be permanent) </li></ul><ul><li>declared in static ahead of time (can't predict how many) </li></ul>
  40. 40. Where do those records come from? <ul><li>What about your homework? </li></ul><ul><li>You read in a file, but you don't know ahead of time how many records there will be. </li></ul><ul><li>You push them onto a vector as you read them. </li></ul><ul><li>Last week we saw that the vector's machinery occupied 20 bytes, regardless of entries.  </li></ul><ul><li>Where are those entries coming from when you use </li></ul><ul><li>push_back? </li></ul>
  41. 41. The Heap <ul><li>Isn't the answer obvious, since we haven't talked about it yet? </li></ul>
  42. 42. The Heap <ul><li>When you use the push back function, </li></ul><ul><li>when you use a constructor function in a class, </li></ul><ul><li>under the covers, without you explicitly asking for it, </li></ul><ul><li>you have invoked the new function, which takes memory from the heap. </li></ul><ul><li>New Syntax: &quot; new &quot; </li></ul><ul><li>eg: </li></ul><ul><li>LocalError * myError = new LocalError(&quot;any message&quot;); </li></ul>
  43. 43. New <ul><li>Remember the LocalError class that we created weeks ago? </li></ul><ul><li>We can create an object of the LocalError type by using new. </li></ul><ul><li>New will return a pointer to an object of type LocalError. </li></ul><ul><li>LocalError * myError = new LocalError(&quot;any message&quot;); </li></ul><ul><li>This syntax is not better or worse than the old syntax,  </li></ul><ul><li>it just illustrates the idea that the memory is new, it was not allocated when the program started. </li></ul><ul><li>And that new memory comes off the heap. </li></ul>
  44. 44. Pieces of the Syntax <ul><li>LocalError * myError = new LocalError(&quot;blablbla&quot;); </li></ul><ul><li>(LocalError *) together, are the type of the variable.  </li></ul><ul><li>This variable is a pointer to type LocalError. </li></ul><ul><li>myError is the name of the variable. </li></ul><ul><li>new means create a new variable from the heap. </li></ul><ul><li>LocalError(&quot;blabla&quot;); remember that the LocalError class had a constructor that took a string as its parameter. </li></ul><ul><li>That's why it's called a constructor. It is a function that builds a new whatever from the heap when it is called. </li></ul>
  45. 45. It's on the Heap. So What? <ul><li>Since it's on the Heap and not on the stack,  </li></ul><ul><li>when stack frames change and stack frame variables go away, </li></ul><ul><li>variables on the heap are still available for use. </li></ul><ul><li>How does your program get to access them? Through POINTERS! </li></ul>
  46. 46. More Images: the Stack <ul><li>  </li></ul>
  47. 47. More Images: Heap and Stack <ul><li>  </li></ul>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.