Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

General Talk on Pointers


Published on

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

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>