170 likes | 183 Views
Pointers. Arrays have a disadvantage: Their size must be known at compile time. We would like the capability to allocate an array-like object of any needed size, at run time. We can use pointers for this! A pointer variable is a variable whose value is an address.
E N D
Pointers • Arrays have a disadvantage: Their size must be known at compile time. • We would like the capability to allocate an array-like object of any needed size, at run time. • We can use pointers for this! • A pointer variable is a variable whose value is an address. • Some programmers use the terms pointer and address interchangeably. • Pointers allow us to manipulate data through its address • This makes pointers very useful but also very dangerous.
Pointers • How can pointers help? • We request a memory block of a certain size • The memory allocation function locates a suitable block (if one exists) and returns its starting address to us. • We save that address in a pointer variable. • We can now access any part of this block, indirectly, through the pointer/address. • CAREFUL: When we are done with this memory, we must "return" it.
Intro to Pointers • Example: address variable name, value px is a pointer variable that contains the address of an integer variable, x. The value of px is address 0xbfffc294 The value of x is integer -10 0xbfffc290: px ,0xbfffc294 0xbfffc294: x , -10 0xbfffc298: We say that px points to x Because x is an int, we say that the base type of px is int
Intro to Pointers • A pointer variable is declared as follows: base_type*variable_name ; the name of the pointer variable. It follows the same rules as regular variables, and usually starts with a p the type of the object pointed to by the pointer the asterisk signifies that this is a declaration of a pointer variable
Intro to Pointers • Examples • All of these variables are currently unitilialized int *pnum; // pnum will contain the address of an // integer float *ptemp; // ptemp will contain the address of a // floating point number char *pword, letter; // CAUTION!pword is a pointer // to char but letter is a char.
Initializing pointer variables • There are several ways to initialize a pointer variable, depending on the intended use. • Intention:We need a pointer to indirectly access an existing object. • We can access the address of a variable by using the & operator. • This is called the referencing operator. You can read it as "address of" int *px, x; px = &x; // px now points to x // Next, we'll see how to access x indirectly
Indirect access • A pointer variable holds an address • We can access the contents at that address by using thedereferencing operator, * • Do not confuse this with the multiplication operator or with the asterisk used in the pointer's declaration. • Example: int *px, x; px = &x; *px = 16; // go to address px (0xbfffc294) and put 16 there. cout << x << endl; // this prints 16 • NEVER dereference an uninitialized pointer 0xbfffc290: px ,0xbfffc294 0xbfffc294: x , 16
Initializing pointer variables • There are several ways to initialize a pointer variable, depending on the intended use. • Intention:We need a pointer to indirectly access an existing object. • If that object is an array, just assign the array name to the pointer: • We can do this, because an array name is the address of the first element of the array. • The difference between an array and a pointer variable is that the array is a constant address. int list[5] = {10, 20, 30, 40, 50}; int *pnum; pnum = list; /* pnum now contains the address where list begins. In other words, it contains the address of the first element of the list. */
Initializing pointer variables • There are several ways to initialize a pointer variable, depending on the intended use. • Intention:We need a pointer to point to an array-like object whose size is determined at runtime. • To do this, we must dynamically (i.e. at runtime) allocate as much memory as we need and set the pointer variable to contain the address where that memory chunk begins. • Dynamic allocation is achieved with the new function. • Furthermore, since the space is now allocated dynamically, we must take care to deallocate it when it is not needed any longer (otherwise, we'll have a so-called memory leak) • Deallocation is achieved with the delete function.
Dynamic allocation int *pnums, size; cout << "How big a list do you want? "; cin >> size; pnums = new int [ size ] ; // note the brackets. // This allocates enough space to // hold size integers (i.e. 4*size bytes) delete [ ] pnums; // ALWAYS deallocate dynamically // allocated space to avoid memory leaks.
Dynamic allocation • We can use new to allocate enough space for just one object. • Example 1: • Example 2: int *px; px = new int; // allocate enough space for one int *px = 15; // indirectly assign a value to that int delete px; // Note the lack of brackets int *px; px = new int(15); // allocate enough space for one int, and // initialize that int to 15. // Example 1 initialized the int through an // assignment. This example initializes it // through a constructor (more on constructors later). delete px;
Pointer arithmetic • A pointer variable holds an address • We may add or subtract an integer to get a different address. • Adding an integer k to a pointer p with base type t will make the value of p equal to p+k*sizeof(t) • Example: int *ptr = new int[3]; int *temp; temp = ptr + 2; // equivalent to temp = &(ptr[2]); delete [] ptr; 0x9961008: ? 0x996100c: ? 0x9961010: ? 0x9961014: ? . . . . . . 0xbff2ebb0: temp ,0x9961010 0xbff2ebb4: ptr ,0x9961008
Basic operations allowed on pointers • Referencing: &px • returns the address where the pointer variable px is located. • Dereferencing: *px • returns the contents of the location pointed to by px • Adding an integer: px+k, px-k • returns the address px+k*sizeof(*px) or px-k*sizeof(*px) • Equality: px == py, px != py • compare two pointers for equality • (sometimes) Relation: px<py, px<=py, px>py, px>=py • ONLY WORKS WHEN px AND py POINT TO THE SAME OBJECT!Otherwise, it's undefined.
Pointer examples char *pletter, *pgrade; char grades[4] = {'A', 'B', 'C', 'D'}; char ch; pgrade = grades;/* pgrade points to the beginning of grades */ pletter = &ch; /* now, pletter points to variable ch */ pletter = pgrade; /* now, pletter points to the beginning of grades */ grades = pletter; /*ILLEGAL! The address of an array is constant! You cannot change its value */ pletter = 100; /*ILLEGAL!100 is an integer, pletter's value should be an address */ pletter = &pgrade /* ILLEGAL!pletter should be the address of a char, but &pgrade is the address of a pointer (or, to be more specific, it's the address of the address of a char). The types do not match. */
NULL pointers • NULL represents a special location in memory that is guaranteed to NOT contain valid data • Dereferencing a NULL pointer will cause a segmentation fault. • Programmers often initialize pointers to NULL to "catch" any unintended dereferencing of a pointer that does not contain valid data. • GOOD IDEA! Always do this! • new typically returns NULL if it fails to allocate memory.
delete • Never try to deallocate the same memory twice • Example: int *pnum, *pcopy; pnum = new int(32); pcopy = pnum; delete pnum; delete pcopy; // ERROR! This space has already been deallocated
delete • The argument to delete should always be the address where the allocated space begins. • Example: int *pnum, *pcopy; pnum = new int; pcopy = pnum; pnum ++; delete pnum; // ERROR! pnum does not point to the beginning of // the allocated space any longer. // delete pcopy; would be the correct way to // deallocate the space.