Pointers The C programming language gives us the ability to directly manipulate the contents of memory addresses via pointers. Unfortunately, this power brings with it the freedom to screw things up spectacularly as simple errors can corrupt the state of your program in ways that make debugging difficult. The goal of these slides is to make sure that you understand exactly what you're doing when you use pointers in your code. The iconic clay figure depicted in this slide is Binky of the claymation Pointer Fun with Binky.
Memory 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB Code and data for your program are stored in random-access memory (RAM), which is basically a huge array of 1 byte (8 bits) blocks. Each block is associated with a hexadecimal number that represents its memory address. Just as ints are variables that store integers and floats are variables that store floating-point values, a pointer is a variable that stores memory addresses. In the appliance (a 32-bit operating), a memory address is 4 bytes, so it makes sense that a pointer is also 4 bytes. 0x8 0x9 0xA 0xB
You should now be able to understand this comic!
<type>* <variable name> Creating Pointers Here's how to declare a pointer in C. Remember that a pointer's value is a memory address. Its type then describes the data located at that address. So in the first example, int* x declares a pointer to 4 bytes of memory that will contain an integer. Declaring pointers: <type>* <variable name> Examples: int* x; char* y; float* z;
Referencing and Dereferencing & is the reference, or address-of, operator. It returns the address in memory at which a variable is stored. * is the dereference operator. A pointer's value is a memory address. When the dereference operator is applied to a pointer, it returns the data stored at that memory address. Referencing: &<variable name> Dereferencing: *<pointer name>
Under the hood... Variable Address Value x 0x04 5 ptr 0x08 copy 0x0C int x = 5; int* ptr = &x; int copy = *ptr; Here are examples of the referencing and dereferencing operators in use. Let's think carefully about what's going on under the hood as each line executes. The first line declares an integer called x. 4 bytes are allotted for x at memory address 0x04, and the value 5 is stored there. The second line declares an int pointer called ptr. 4 bytes are allotted for ptr at memory address 0x08, and the address of x is stored there. The third line declares an integer called copy. 4 bytes are allotted for copy at memory address 0x0C, and the value of the integer that ptr is pointing to is stored there.
Track the values x ptr 5 &x 35 int x = 5; int* ptr = &x; *ptr = 35; Let's track the values of these variables as each line executes: In the first line, x is initialized to 5. In the second line, ptr is assigned x's memory address. x remains 5. In the third line, we dereference ptr (aka, go to the value it is pointing to) and change that value to 35.
Test Yourself a b c pa pb pc 1. 2. 3. 4. 5. 6. 7. Test yourself by tracking the values of these variables just as we did in the previous slide.
Answers a b c pa pb pc a = b * c; a *= c; b = *pa; pc = pa; 20 4 5 &a &b &c 100 500 10000 50000 a = b * c; a *= c; b = *pa; pc = pa; *pb = b * c; c = (*pa) * (*pc); *pc = a * (*pb); int a = 3, b = 4, c = 5; int* pa = &a, *pb = &b, *pc = &c; Answers to last slide's exercise!
Pointer Arithmetic Adding/subtracting n adjusts the pointer by n * sizeof(<type of the pointer>) bytes x y 5 0x04 0x08 You can adjust pointers by adding or subtracting an integer. Adding or subtracting n adjusts the pointer by n * sizeof(<pointer type>) bytes. For example, in the code on this slide, y is a pointer to an int called x, which is stored at 0x04. Therefore, adding 1 to y shifts the value of y by 1 * sizeof(int) or 4 bytes. int x = 5; int* y = &x; y += 1;
What will print? int main(void) { char* str = "happy cat"; int counter = 0; for (char* ptr = str; *ptr != '\0'; ptr++) counter++; } printf("%d\n", counter); Pay close attention to the syntax of this for loop. ptr starts out pointing to the first character of the string. Incrementing ptr shifts the pointer by 1 * sizeof(char)or 1 byte, moving ptr to the next character in the string. After the loop executes, the length of the string will be printed.
1 2 3 Pointers and Arrays 1 2 int array[3]; *array = 1; 1 2 1 2 3 int array[3]; *array = 1; *(array + 1) = 2; *(array + 2) = 3; Under the hood, an array is treated like a pointer to its first element, so standard pointer arithmetic applies: *array is equivalent to array[0] *(array+1) is equivalent to array[1] *(array + 2) is equivalent to array[2].