240 likes | 417 Views
Pointers. Dr. Jose Annunziato. Variable Addresses. Variable declarations allocate enough bytes to hold the variable type. Each byte has a particular address The address of the variable is the address of the first byte allocated for the variable Consider the following variables
E N D
Pointers Dr. Jose Annunziato
Variable Addresses • Variable declarations allocate enough bytes to hold the variable type. Each byte has a particular address • The address of the variable is the address of the first byte allocated for the variable • Consider the following variables char letter; short number; float amount; • Address operator & gets a variable's address
Address Operator • The & operator returns the address of a variable • The sizeof() function returns the number of bytes float balance = 250.75; cout << "Balance = " << balance << endl; cout << "Address of balance: " << &balance<<endl; cout << "Size balance: " << sizeof(balance) << endl;
Pointer Variables • Pointer variables, or pointers, can hold the address of another variable • Use the asterisk, *, after a data type to declare a pointer to a variable of that type float *balance; // balance points to a float int *type; // type points to an int • The asterisk can be on the type instead of variable float* balance; // it's the same. Emphasizes int* type; // pointer to type
Creating and Using Pointers • Use the dereference operator, *, on a pointer to operate on the variable pointed to float balance = 5000.0; float* ptr; ptr = &balance; cout << balance << endl; cout << *ptr << endl; // access original variable *ptr = 6000.0; // change original variable cout << *ptr << endl;
Using Pointers • Pointers can point to various variables float balance = 500.0, float amount = 600.0; float* ptr; ptr = &balance; *ptr += 100; // depositing 100 ptr = &amount; *ptr = *ptr * 1.05; // adding 5% interest
Arrays and Pointers • Arrays are already pointers • Array names refer to the first element • Array indices compute address of elements based on address of first element • Indices advance as many bytes as the type of each element requires float balance[3];
Pointer Arithmetic • We can address array elements with pointer arithmetic float balance[] = {10, 20, 30, 40}; cout << balance << endl; // address of 1st cout << *balance << endl; // balance[0] ptr = balance; // notice not &balance ptr + 1 // &balance[1] ptr + 2 // &balance[2] *(ptr + 3) // balance[3]
Pointer Arithmetic float balance[] = {10, 20, 30, 40}; *balance == balance[0] *(balance + 1) == balance[1] *(balance + 2) == balance[2] *(array + index) == balance[index]
Iterating Over Arrays with Pointers float balance[] = {1,2,3,4}; float* ptr = balance; for ( int k = 0; k < 4; k++ ) { 1,2,3,4, cout << *ptr << ", "; ptr++; } for ( int k = 0; k < 4; k++ ) { 4,3,2,1, ptr--; cout << *ptr << ", "; }
Comparing Pointers • When comparing pointers, we are comparing addresses • Use relational operators ==, !=, >, >=, <, <= to compare relations between two pointers • To compare the values the pointers refer to, deference the pointers to compare the original values; int a = 10, b = 10; int* ptr1 = &a, ptr2 = &b; ptr1 == ptr2 ? … : …; *ptr1 == *ptr2 ? … : …;
Pointers as Function Parameters • Pointers allow passing by reference and manipulating the original variable void giveRaise ( float* stipend, float raise ) { *stipend += raise; } int main() { float salary = 10000.0; giveRaise ( &salary, 1000.0 ); cout << salary << endl; }
Pointers as Function Parameters • Use the & operator for easier pass by reference void giveRaise ( float &stipend, float raise ) { stipend += raise; } int main() { float salary = 10000.0; giveRaise ( salary, 1000.0 ); cout << salary << endl; }
Note on Parameter Names • Parameter names are local variables, their names don’t have to match variable being passed in void giveRaise ( float* stipend, float raise ) { *stipend += raise; } int main() { float salary = 10000.0; giveRaise ( &salary, 1000.0 ); }
Note on Parameter Names • When forward declaring a function, the name of the parameter is optional since it's not going to be used yet • It's, of course, mandatory in the function definition void giveRaise ( float *, float ); int main() { float salary = 10000.0; giveRaise ( &salary, 1000.0 ); } void giveRaise ( float* stipend, float raise ) { *stipend += raise; }
Passing Arrays to Functions • As we saw earlier, pointers and arrays are closely related and array names are pointers to 1st element • Function parameters accepting arrays can be declared as pointers instead of arrays: float average ( float values[], int size ) { … } • Is equivalent to: float average ( float *values, int size ) { … } • Manipulate array in function using array indices or pointer arithmetic. It's the same
Dynamic Memory Allocation • Pointers allow allocating memory space at run time • Use the new operator to allocate new space • The new memory space is accessible by the address to the 1st byte of the data structure int* intPrt; // will hold the address intPtr = new int; // of the new data *intPtr = 25; // dereference to modify cout << *intPtr; cin >> *intPtr; total += *intPtr;
Deallocating Memory • Memory that has been allocated with new can be deallocated using delete int* ptr = new int; delete ptr; • Do not deallocate memory that has not been allocated with new
Array Sizes are Constants • A common use of dynamic memory allocation is to create arrays of an unknown size • Declared array sizes must be constants const int SIZE = 100; float balances [ 100 ]; float amounts [ SIZE ]; • You can not use a variable as the size of a declared array int size; cin >> size; float balances [ size ];
Allocating Dynamic Arrays • Arrays can be allocated dynamically using the new operator and assigning the address to a pointer int size; cin >> size; float* amounts = new float [ size ]; • You can then use regular array index syntax: amounts [ 0 ] = 123.23; amounts [ 1 ] = 234.56;
Returning Pointer from Functions • Functions can create dynamically allocated structures and return pointers to them float* createFloatArray ( int size ) { float* floats = new float [ size ]; return floats; } • You can then use the pointer as an array int length; cin >> length; float* balances = createFloatArray ( length ); balances [ 0 ] = 234.56;
Careful Returning Out of Scope Structures • When returning structures allocated in a function, careful it is not a structure that will be destroyed when the function returns string* createStringArray () { string descriptions [ 100 ]; return descriptions; } • Above, the descriptions array is a local variable and will be destroyed when the function returns
Returning Pointer from Functions • This function works because it returns the address of the dynamically allocated structure string* createStringArray ( int size ) { string* strings = new string [ size ]; return strings; } • Above, even though the stringsvariable is destroyed when the function terminates, the value is returned as an address that can be used to retrieve the original array • The array still exists since delete has not be called