Pointers: Part I
Why pointers? - low-level, but efficient manipulation of memory - dynamic objects Objects whose memory is allocated during program execution. ( Dynamic objects can survive after the function ends in which they were allocated). Dynamic objects allow flexible-sized arrays and lists
Computer Memory and Variables A variable is a symbolic name assigned to some memory storage The size of this storage depends on the type of the variable: one byte char, 4 bytes int The name of variable is in ‘symbol table’ by compiler: each symbol is associated with its type, location, scope … So, the compiler manages its location good for programmers! 100 …… Memory address:1024 … 1020 Symbol table a: int, 1024, … int a=100;
Pointers A pointer is a variable used for storing the address of a memory cell. We can use the pointer to reference this memory cell, so to ‘manipulate’ it! 100 ……1024… Memory address: … 1020 Integer a Pointer p n Object whose value represents the location (memory address) of another object int a; int* p;
Define a pointer type variable Examples of (uninitialized) pointers int* ip; char* s; int *ip; // ip is a pointer to an int char *s; // s is a pointer to a char TypeName *variablename; int *p; Each type of object (variable) has a pointer type, therefore a pointer variable of that type. TypeName* variablename; int* p; equivalent
Getting an address: address operator & int a=100; “&a” “the address of a” 100………… Memory address:1024 int a = 100; cout << a; 100 Cout << &a; 1024 … 1020 a
Store the address in a pointer variable The value of pointer p is the address of variable a 10088…1024… Memory address: … 1020 ap int a = 100; int* p = &a; cout << a << " " << &a <<endl; cout << p << " " << &p <<endl; Result is: p is pointing to a A pointer is also a variable, so it has its own memory address
Dereferencing Operator * We can access to the value stored in the variable pointed to by preceding the pointer with the “star” operator (*), 10088…1024… Memory address: … 1020 int a = 100; int* p = &a; cout << a << endl; cout << &a << endl; cout << p << " " << *p << endl; cout << &p << endl; a p *p gives 100
An asterisk (‘*’) has two usages In a definition, an asterisk indicates that the object is a pointer. char* s; // s is of type pointer to char (char *s; is possible) In expressions, an asterisk before a pointer indicates the object the pointer pointed to, called dereferencing int i = 1, j; int* ptr; // ptr is an int pointer ptr = &i; // ptr points to i j = *ptr + 1;// j is assigned 2 cout << *ptr << j << endl; // display " 12 "
Summary on two operators * and & * has two usages: - pointer - dereferencing & has two usages: - getting address - reference (‘call by ref’, see later)
Null Address 0 is a pointer constant that represents the empty or null address Indicates that pointer is not pointing to storage of a valid object Cannot dereference a pointer whose value is null int* ptr; ptr = 0; cout << *ptr << endl; // invalid, ptr // does not point to // a valid int
Example #include using namespace std; int main (){ int value1 = 5, value2 = 15; int* p1; int* p2; p1 = &value1; // p1 = address of value1 p2 = &value2; // p2 = address of value2 *p1 = 10; // value pointed to by p1=10 *p2 = *p1; // value pointed to by p2= value // pointed to by p1 p1 = p2; // p1 = p2 (pointer value copied) *p1 = 20; // value pointed to by p1 = 20 cout << "value1==" << value1 << "/ value2==" << value2; return 0; } Result: Value1 is 10 Value2 is 20
Another Pointer Example int a = 3; char s = ‘z’; double d = 1.03; int* pa = &a; char* ps = &s; double* pd = &d; cout << sizeof(pa) << sizeof(*pa) << sizeof(&pa) << endl; cout << sizeof(ps) << sizeof(*ps) << sizeof(&ps) << endl; cout << sizeof(pd) << sizeof(*pd) << sizeof(&pd) << endl;
Writing pointer type properly in C++ … int *a, *b; a, b are both integer pointers int* a, b; a is integer pointer, b is just integer! typedef int* IntPt; IntPt a, b; typedef int MyInt; MyInt k; int k; int* a; int* b; ? Recommended:
Traditional Pointer Usage void swap(char* ptr1, char* ptr2){ char temp = *ptr1; *ptr1 = *ptr2; *ptr2 = temp; } int main() { char a = 'y'; char b = 'n'; swap(&a, &b); cout << a << b << endl; return 0; } Use pass-by-value of pointers to ‘change’ variable values C language does not have ‘call by reference’, only ‘call by value’!
Reference: X& l int& b a; l b is an alternative name for a void f(int& b) {}; int main() { int a; f(a); }
Pass by reference (better than ‘pointers’) void swap(char& y, char& z) { char temp = y; y = z; z = temp; } int main() { char a = 'y'; char b = 'n'; swap(a, b); cout << a << b << endl; return 0; } y, z are ‘references’, only names, not like ptr1, ptr2 that are variables
it is also possible (not recommended)… void swap(char &y, char &z) { char temp = y; y = z; z = temp; } int main() { char a = 'y'; char b = 'n'; swap(a, b); cout << a << b << endl; return 0; } This is just an alternative way of writing ‘reference’.
Pointers and arrays
Arrays are pointers! The name of an array points only to the first element not the whole array
#include Using namespace std; void main (){ // Demonstrate array name is a pointer constant int a[5]; cout << "Address of a[0]: " << &a[0] << endl << "Name as pointer: " << a << endl; } /* result: Address of a[0]: 0x0065FDE4 Name as pointer: 0x0065FDE4 */ Array name is a pointer constant
Result is: 2 #include Using namespace std; void main(){ int a[5] = {2,4,6,8,22}; cout << *a << " " << a[0] << " " << *(&a[0]);..." } //main a[4] a[0] a[2] a[1] a[3] Dereference of an array name This element is called a[0] or *a
To access an array, any pointer to the first element can be used instead of the name of the array. We could replace *p by *a #include Using namespace std; void main(){ int a[5] = {2,4,6,8,22}; int* p = a; int i = 0; cout << a[i] << " " << *p;... } a[4] a[0] a[2] a[1] a[3] a p a Array name as pointer 2 2
Multiple Array Pointers Both a and p are pointers to the same array. 2 4 #include Using namespace std; void main(){ int a[5] = {2,4,6,8,22}; int* p = &a[1]; cout << a[0] << " " << p[-1]; cout << a[1] << " " << p[0];... } a[4] a[0] a[2] a[1] a[3] p P[0] A[0]
Pointer Arithmetic Given a pointer p, p+n refers to the element that is offset from p by n positions a a + 2 a + 4 a + 3 a + 1 p p + 2 p + 3 p - 1 p + 1
*(a+n) is identical to a[n] Dereferencing Array Pointers a[3] or *(a + 3) a a + 2 a + 4 a + 3 a + 1 a[2] or *(a + 2) a[1] or *(a + 1) a[0] or *(a + 0) a[4] or *(a + 4)
Summary * two usages: - pointer type definition: int a; int* p; - dereferencing: *p is an integer variable if p = &a; & two usages: - getting address: p = &a; - reference: int& b a; b is an alternative name for a First application in passing parameters (‘swap’ example) int a=10; int b=100; int* p; int* q; p=&a; q=&b; p = q; *p = *q; ? ?
A[n]: like a vector, an array *(a+n): like a ‘sequence’ or a ‘list’ Two ways of manipulating an array