Transcript for:
Understanding Pointers in C Programming

I've been programming in c for almost 40 years and I've understood pointers for about 39 of those years but that first year was a process of flailing and wondering and being confused by the arrows and the dots and the Stars until I finally got what pointers were my C code was weak and ineffectual pointers underlie everything that makes C powerful and today I'm going to explain them in detail hopefully in a way that makes the big light bulb come on for you even folks who understand and use pointers regularly are likely to find some tips that will be new and useful so stay tuned I think pointers are scary for everyone when you first get introduced to them this is especially true if you're coming to see from a language like Java or python where they're not something that you commonly see just when you think you've got programming sorted out you make the jump to C and it's just a massive pointers and punctuation well rest assured pointers are only scary because they look that way they're actually an incredibly simple concept once you understand them and today I'm going to try and get you over that hump let's consider the analogy of a house perhaps in C we can define a house like this as a structure that keeps track of the number of square feet the house has the number of bedrooms and the number of bathrooms we create a house object in our code whether it's a global variable or just a local one and as you're likely aware the house object is stored somewhere in the computer's memory and all the memory in your computer is numbered with an address from byte zero on up to the top of memory our house object has three integer values so it's going to be 12 bytes of storage in total the compiler finds a place for it and puts it there and that's all there is to it now we normally have no idea where in memory our house is going to be stored but let's say in this case it gets placed at address 2326. now what if you want to tell someone that there's a party at this house how would you go about it well you could drive to the house all the way across town and show each person that's being invited which house it is and where it is but you wouldn't likely do that would you what would you do well you'd give them the address you'd say hey the street address is 2326 stop by and BYOB that's way easier than taking everyone there in advance to show them or Worse creating an entire copy of the house to demonstrate what it looks like so they can recognize it and at its core that's all that a pointer is a variable that holds the address of some object it's just the memory address of something interesting like a house or in see it might be a structure or a string or even a simple integer but if you create a pointer to something all you're doing is storing its memory address in a variable that we call a pointer what makes pointers powerful is that you can access and use the object that's being pointed to by the pointer you don't need a whole copy of the house object you just need to know its address let's look at an example so simple that it's painful on the Commodore 64 you can change the background color of the screen by changing the byte and memory at address 53 to 81. if you set it to zero the screen will turn black now how would you do that in C well we know two things we know the type which is a byte and its address which is 53 to 81. so we create a byte pointer called P background color and set it to point to address 53 to 81. and see when we're creating a pointer we add a star in front of the variable name to indicate that it's a pointer so for a pointer to a byte in memory we declare it as byte star P background color syntactically that means that P background color is a pointer to a byte in memory it's a variable that will hold the address of a byte so P background color is a pointer and it points that as 53281 but now how do we change the contents of that address well in C we use the star operator again putting a star in front of the variable name when you're using it means that you're referring to the thing being pointed at or put another way at the contents pointed to by the pointer in this case it's a byte so star P background color means the contents of a memory location 53 to 81. when we store a zero at that location the screen will turn black one little syntactic caveat about such declarations the star must proceed each variable name that you're declaring as a pointer it decorates the variable not the type name so if you were to write if star X comma y you're declaring one pointer to an integer and one actual integer if you wanted two pointers both would have to have the star pointers to bytes and integers are all well and good but what about pointers to more complicated things like objects let's create a house using our house class the one that includes the square footage the bedrooms and the bathrooms we'll give it the same specs as the house I grew up in 960 square feet two bedrooms one bathroom and dad got first dibs on the bathroom if we want to print out information about the members of the house structure like the number of bedrooms we use the dot operator the dot operator indicates you're looking for a member variable of the class the only difference when using a pointer is that you use the arrow operator in the pointer instead of the dot operator on the object the arrow means go to the object being pointed to and then get this member variable by its name the arrow is the same as a dot but it indicates you're using a pointer to the object and not just the object itself here we have two versions of the get house price function both price the house in the exact same way but the first version accepts an actual house object as an argument when a caller calls this function the house object they provide will be copied and used as the argument within this function depending on the size and complexity of the house structure that could be an expensive and wasteful operation why is it wasteful well because just like in real life there's no reason to bring your house to the appraiser for an appraisal the appraiser comes to you based on the address of the house and that's what our second version of the function does it accepts a pointer to the house or The house's address and then uses the arrow operator in exactly the same way as the first function use the dot operator the difference is the second version is using a pointer it indirects through the pointer and looks up the members of the object that is pointed to another way to look at it is that the first version of the function accepts an argument in a pass-by-value manner and the second is passed by reference pass by value means that the object is passed as a complete copy passed by reference means you're just passing the address of the object in the form of a pointer pass by reference is usually far faster and more efficient than pass by value at least for larger types on a 32-bit system a pointer is four bytes and so that's all that's passed to the function no matter how big or complicated the object being pointed to is now that you hopefully have a basic grasp of what a pointer is we can talk about some important concepts related to pointers the first we've already seen and that is the concept of indirection the main thing to remember about pointers is that they do not hold any actual values or types but instead hold the address of those values in other words they point to the location of memory where the values are stored and hence the name pointer this level of indirection is often the most difficult concept for new programmers to grasp another important distinction is between arrays and pointers it's common for beginners to be confused between pointers and arrays as they sometimes can be used interchangeably however they are fundamentally different an array is a contiguous chunk of memory holding multiple values of the same type like a character string a pointer on the other hand is a variable that holds the address of the first value the big light bulb moment often happens when the one finally understands that when an array is used as a pointer it decays into a pointer to its first element after all if your pointer points to the first element of an array of objects in memory as long as you know how many elements there are and where they start using a pointer to an array is largely the same as using the array itself pointer arithmetic is another complex aspect to grasp mainly because it involves manipulating memory addresses directly it's a big moment of realization here often happens when you realize that adding or subtracting from a pointer value actually moves it by a multiple of the size of the type that it points to not by just one byte now if you've got a pointer to a character string in memory every time you increment the pointer the address it contains will step forward one byte because each character is one byte but if you've got a pointer to 32-bit integers however every time you increment the pointer or add one to it the pointer will step ahead by four bytes because that's the size of the objects that are being pointed to and so if you had a pointer to an array of house objects every time you incremented the pointer it would step by 12 bytes since that's the size of the structure likely the most common pointer you'll run into is the character pointer a character pointer or sometimes called care pointer or Char pointer contains the address of the first byte of a string in memory and C strings are terminated at the End by a zero byte you can almost treat a character pointer and an array of characters as being the same thing and most of the time you'll be right the primary difference is that a pointer is a variable that contains the address whereas an array is syntactic sugar for the actual memory address furthermore the size of an array is its actual size the memory bytes that it takes up whereas the size of the pointer will just be 32 or 64 bits depending on your system among the more esoteric features that you might encounter are Pointers two pointers pointers can point to other pointers leading to multiple levels of indirection this concept is a bit tough to understand but it's crucial when dealing with Dynamic data structures like trees and graphs as perhaps the simplest example of a pointer to a pointer let's imagine that we have a character string and a pointer called P which points to the first byte of it we then create a pointer to a pointer indicated by the two stars and set it to the address of the first pointer so at this point P points to the string itself and P1 points to p that means if we indirect from P1 by using the star operator in front of it we get that original pointer we can output that to the console just like any other pointer to a string because the contents of a pointer to a pointer is just that pointer to the string the other thing you should be aware of is the difference between a null pointer and an uninitialized pointer understanding that an uninitialized pointer and a null pointer are not the same can be a significant point of understanding an uninitialized pointer has an indeterminate or random value whereas a null pointer is a pointer that does not point to any object or function in C a null pointer is set to zero but an uninitialized points are just randomly points and is useless until it's initialized with the address of a real object once you start working with pointers particularly if you do any memory allocation and management you will undoubtedly run into the concept of the Void pointer avoid pointer points to an address in memory like any other pointer but it has no notion of what lives there could be a house it could be an integer it could be a string it doesn't matter it's just the address a void pointer just points to the address and has to be converted or cast to an object pointer before you can really use it for anything the void pointer simply stores the memory address with no type information why would such a thing exist well imagine you're writing the Malik API that allocates and returns a block of memory as the API writer you have no idea what kind of object the user will ultimately place there in memory You're simply asked for a block of memory of so many bytes and you return the address of it and so you return it as a void pointer not knowing what it is the caller is then free to cast that memory to almost any type they wish such as a house object imagine that in our code we Malick and request enough bytes to hold a house Malik returns a void pointer which we immediately cast to be a house pointer and now we can operate on that block of memory as though it has always been a house finally we have function pointers which are probably the most complicated format you'll routinely run into a function pointer does two things like any other pointer it contains the address of something which in this case is the address of a piece of code that implements a function it also defines the arguments and return value to be expected when the function is called the function pointer then is a pointer that points to a function instead of to a data type this enables you to dynamically change which function is called in your program you can think of function pointers as similar to normal pointers but instead of referring to data values like an enter or care they point to a piece of executable code here's how you can declare a function pointer here P add is a pointer to a function that takes two integers as arguments and returns an integer the parentheses around star P add are necessary because of the operator precedence without them the Declaration would be parsed as a function declaration and not a function pointer you can assign the address of the function add to the function pointer like this and then you can use the function pointer to call the function this will call the add function with the arguments five and three and the result which is 8 will be stored in the variable sum note that the parentheses around star P add are required when calling through the function pointer as well function pointers are often used in C for callbacks that is passing a function to another function for example the Q sort function in the C standard Library uses a function pointer to allow the programmer to specify how the elements should be compared for sorting in other words when it has to compare two elements in an array that it's going to sort it asks you which one is greater it does that by calling your function to determine the answer and it knows what function to call because you give it a function pointer to your comparison function here's an example of how you could use q-sort with a custom comparison function in this code compare is a function that takes two void pointers and converts them into end pointers and then compares the integers that those pointers point to the Q start function uses this compare function to determine the order of the elements when sorting the numbers array a word of caution while function pointers are a powerful tool they can also make your code a lot harder to read if used carelessly they should generally be used sparingly with a clear comma to explaining what the function pointer is for in summary function pointers in C allow you to store and pass around references to functions in your program they're used extensively for providing flexible interfaces implementing callback mechanisms and creating data structures that can handle operations in a types generic way however they require a good understanding of the C type system to use effectively and safely if you've enjoyed today's episode on pointers remember I'm not selling anything and I'm mostly in this for the subs and likes so please be sure to leave me one of each before you go today in the meantime and in between time I hope to see you next time right here in Dave's Garage