Presentation is loading. Please wait.

Presentation is loading. Please wait.

Pointers.

Similar presentations


Presentation on theme: "Pointers."— Presentation transcript:

1 Pointers

2 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

3 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! Object whose value represents the location (memory address) of another object Memory address: 1020 1024 10032 100 1024 int a; int* p; Integer a Pointer p

4 Getting an address: address operator &
int a=100; “&a”  “the address of a” Memory address: 1020 1024 100 a int a = 100; cout << a;  100 Cout << &a;  1024

5 Define a pointer type variable: T*
Each type of object (variable) has a pointer type, therefore a pointer variable of that type. TypeName* variablename; int* p; equivalent TypeName *variablename; int *p; 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

6 Store the address in a pointer variable
Memory address: 1020 1024 10032 88 100 1024 a p int a = 100; int* p = &a; cout << a << " " << &a <<endl; cout << p << " " << &p <<endl; Result is: The value of pointer p is the address of variable a A pointer is also a variable, so it has its own memory address p is pointing to a

7 Dereferencing Operator *
We can access to the value stored in the variable pointed to by preceding the pointer with the “star” operator (*), Memory address: 1020 1024 10032 88 100 1024 a p int a = 100; int* p = &a; cout << a << endl; cout << &a << endl; cout << p << " " << *p << endl; cout << &p << endl; *p gives 100

8 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"

9 Summary on two operators * and &
* has two usages: - pointer - dereferencing & has two usages: - getting address - reference (‘call by ref’, see later)

10 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

11 Example #include <iostream> 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

12 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;

13 Writing pointer type properly in C++ …
Recommended: int* a; int* b; ? int *a, *b; a, b are both integer pointers int* a, b; a is integer pointer, b is just integer! typedef int MyInt; MyInt k; int k; typedef int* IntPt; IntPt a, b;

14 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’!

15 Reference: T& void f(int& b) {}; int main() { int a; int& b a; f(a);
b is an alternative name for a

16 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

17 Pointer to ‘Struct’ struct Date {…}; Date d={1,10,2009};
Date* pd = &d; (*pd).day=2; (*pd).month=11; Or pd->day=2; pd->month=11;

18 Pointers and arrays

19 Arrays are pointers! The name of an array points only to the first element not the whole array. 1000 1004 1008 1012 1016

20 Array name is a pointer constant
#include <iostream> 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 */ &a = &a[0] = a, But its semantics is not that clear An array name is converted to a pointer to the first element most of the time. The official standard terminology is that an array name is converted to a pointer to the first element when used in a value context as opposed to an object context. A value context is when you're retrieving and subsequently using the value of an object, such as the right hand side of x = y; . An object context is when you're modifying or querying the object itself, not the value it contains. The left hand side of x = y; is one example.

21 Dereference of an array name
#include <iostream> Using namespace std; void main(){ int a[5] = {2,4,6,8,22}; cout << *a << " " << a[0] << " " << *(&a[0]); ..." } //main a[0] 2 Result is: 2 a[1] 4 a[2] 6 a[3] 8 a[4] 22 This element is called a[0] or *a

22 Array name as pointer 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 <iostream> Using namespace std; void main(){ int a[5] = {2,4,6,8,22}; int* p = a; int i = 0; cout << a[i] << " " << *p; ... } 2 4 8 6 22 a[4] a[0] a[2] a[1] a[3] a p 2 2 a

23 Multiple Array Pointers
Both a and p are pointers to the same array. #include <iostream> 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[0] 2 2 4 4 a[0] 2 p a[1] 4 a[2] 6 P[0] a[3] 8 a[4] 22

24 Pointer Arithmetic Given a pointer p, p+n refers to the element that is offset from p by n positions. 2 4 8 6 22 p - 1 a p a + 1 p + 1 a + 2 p + 2 a + 3 a + 4 p + 3

25 Dereferencing Array Pointers
a[0] or *(a + 0) 2 4 8 6 22 a a + 2 a + 4 a + 3 a + 1 a[1] or *(a + 1) a[2] or *(a + 2) a[3] or *(a + 3) a[4] or *(a + 4) *(a+n) is identical to a[n]

26 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; ? ?

27 Two ways of manipulating an array
a[n]: like a vector, an array a+n *(a+n): like a ‘sequence’ or a ‘list’ ‘a’ points to the first element

28 Dynamic Objects

29 Memory Management Static Memory Allocation Dynamic Memory
Memory is allocated at compiling time Dynamic Memory Memory is allocated at running time { int a[200]; } { int n; cin >> n; a[n]??? }

30 Static vs. Dynamic Objects
Static object Memory is acquired automatically Memory is returned automatically when object goes out of scope Dynamic object Memory is acquired by program with an allocation request new operation Dynamic objects can exist beyond the function in which they were allocated Object memory is returned by a deallocation request delete operation

31 Creating a variable (object): new T
Syntax ptr = new SomeType; where ptr is a pointer of type SomeType Example int* p = new int; p Uninitialized int variable ‘new’ does two things: Create a variable of given type Point the pointer p to the variable

32 Destructing a variable (object): delete p
Syntax delete p; storage pointed to by p is returned to free store and p is now undefined Example int* p = new int; *p = 10; delete p; ‘delete’ does two things: Return the pointed object to the system Point the pointer p to NULL p 10

33 Dynamic Arrays (a collection of variables)
p = new T[size]; delete[] p; Syntax for allocation: p = new SomeType[Expression]; Where p is a pointer of type SomeType Expression is the number of objects to be constructed -- we are making an array Syntax for de-allocation: delete[] p; Because of the flexible pointer syntax, p can be considered to be an array C++ keeps track of the size of the ‘dynamically allocated’ array from the heap, This size is kept by the system, that’s why ‘delete[]’ knows the size.

34 Example Dynamic Memory Allocation p p p
Request for “unnamed” memory from the Operating System int* p, n=10; p = new int; p = new int[100]; p p p = new int[n]; p

35 Freeing (or deleting) Memory

36 Allocation Example Need an array of unknown size int grades[n]; main()
{ int n; cout << “How many students? “; cin >> n; int* grades = new int[n]; for(int i=0; i < n; i++){ int mark; cout << “Input Grade for Student” << (i+1) << “ ? :”; cin >> mark; grades[i] = mark; } . . . printMean( grades, n ); // call a function with dynamic array

37 Dangling Pointer Problem
int* A = new int[5]; for(int i=0; i<5; i++) A[i] = i; int* B = A; delete[] A; B[0] = 1; // illegal!

38 Memory Leak Problem int* A = new int[5]; for(int i=0; i<5; i++)
A[i] = i; A = new int[5]; A 1 2 2 3 4

39 Summary Static variables (objects) Dynamic variables (objects)
A (direct) named memory location A static part (pointer) + (indirect) nameless memory location (dynamic part) int a; a = 20; int* pa; pa = new int; *pa = 20; 20 20 a pa static dynamic static

40 int* p = new int; int* p = new int[100]; *p = 10;
Dynamic array Simple dynamic variable int* p = new int; *p = 10; delete p; int* p = new int[100]; for (i=1;i<100,i++) p[i] = 10; delete[] p; 10 10 p 10 p 10 ‘delete’ two actions: Return the object pointed to Point the pointer p to NULL ‘delete p’ is not sufficient for an array!!!

41 Good practice Logically, Initialize a pointer with NULL
Always check a pointer before usage if (p != NULL) *p

42 n=100; int* p = new int[n]; { int n; cin >> n; N=150; a[n]???
Bad examples n=100; int* p = new int[n]; N=150; P[130]??? { int n; cin >> n; a[n]??? } It’s possible, but not standard, Do: int* a = new int[n]; No! the array stays with the size 100.

43 More pointers

44 Pointers to pointers

45 Pointer to pointer: T**
int a; int* p; int** q; a = 58; p = &a; q = &p; a p q 58 a, *p, and **q are the same object whose value is 58! But q = &a is illegal!

46 Pointer to pointers and 2D arrays

47 Pointer of pointers & 2D Arrays
What is **table ? table[i][j] table table[0] or *( table + 0 ) table + 1 table[1] or *( table + 1 ) table + 2 table[2] or *( table + 2 ) int table[3][4]; for(int i=0; i<3; i++){ for(int j=0; j<4; j++) cout << *(*(table+i) +j); cout << endl; }

48 table and table[0] are of the same address
int table[2][2] = {{0,1}, {2,3}}; cout << table << endl; cout << *table << endl; //same as above cout << table[0] << endl; // same as above cout << *table[0] << endl; cout << table[0][0] << endl; // same as above cout << **table << end; // same as above 0xffbff938

49 Array of Pointers & Pointer to Array
b c A pointer to an array An array of Pointers int a = 1, b = 2, c = 3; int* p[5]; p[0] = &a; p[1] = &b; p[2] = &c; int list[5] = {9, 8, 7, 6, 5}; int* p; p = list;//points to 1st entry p = &list[0];//points to 1st entry p = &list[1];//points to 2nd entry p = list + 1; //points to 2nd entry

50 A Dynamic Table table table[0] table[1] table[2] table[3] table[4]
A dynamic table is an array of pointers to save space when not all rows of the array are full. table[0] table[1] table[2] table[3] table[4] table[5] table int** table; table = new int*[6]; table[0] = new int[4]; table[1] = new int[7]; table[2] = new int[1]; table[3] = new int[3]; table[4] = new int[2]; table[5] = NULL;

51 32 18 24 12 42 14 19 16 11 13 22 table table[0] table[1] table[2]
*(*(table+i)+j) is table[i][j] table[0][0] = 32; table[0][1] = 18;

52 Create a matrix of any dimensions, m by n:
Ideas: Put it into a function: int main() { int m, n; cin >> m >> n >> endl; int** matrix; matrix = imatrix(m,n); } int** imatrix(int m, int n) { int** mat; mat = new int*[m]; for (int i=0;i<n;i++) mat[i] = new int[n]; return mat; int m, n; cin >> m >> n >> endl; int** mat; mat = new int*[m]; for (int i=0;i<m;i++) mat[i] = new int[n];

53 Dynamic matrix deallocation
for(int i=0; i<6; i++) delete[] mat[i]; delete[] mat; void deleteImatrix(int** mat, int m, int n) { for(int i=0; i<m; i++) delete[] mat[i]; delete[] mat; } Each row must be deleted individually Be careful to delete each row before deleting the table pointer.

54 Examples: main() arguments
int main()  int main(int argc, char* argv[]) E.g. a.out int main(int argc, char* argv[]) { if (argc != 3) { troubles!!!} int rows = atoi(argv[1]); int col = atoi(argv[2]); } ‘argc’ is the actual number of arguments ‘argv’ is an array of char*, each pointing to a character

55 Constantness: object or pointer?

56 (const) object (*const) pointer
‘const’ only modifies a type const T* p  constant T, so constant object, const *p ‘const’ only modifies a type as it might be one of them: const T* p const T *p T *const p  constant pointer const T *const p  = constant pointer to constant object (both pointer AND object are constants!) No ‘const*’ operator.

57 Example: A constant object with ‘const’: const int* p;
A constant pointer with ‘*const’: int *const p; A constant object AND pointer is: const int *const p; 57

58 ‘const object’ and ‘constant pointer’
Pointer to const object: the content is const, pointer is free int x=10, y=20; const int* pc = &x; pc = &y // OK *pc = 5; // wrong! Const pointer: the pointer is const, content is free Int *const cp = &x; *cp = 5; // OK cp = &y; // wrong!  int const *pc

59 Because of ambiguous ‘const int** b’ and ‘const int **b’,
so it is ‘const int’! int main(){ int** iptr; int i, j; iptr = new int*[10]; for( i = 0; i < 10; i++ ) iptr[i] = new int[10]; for( j = 0; i < 10; i++ ) iptr[i][j] = i*j; f1(iptr); f2(iptr); f3(iptr); } void f1(const int** bar){ bar[1][1] = 5; // wrong: change int bar[1] = new int[3]; // ok } void f2(int *const *bar){ bar[1][1] = 5; // ok bar[1] = new int[3]; // wrong: change int* bar = new int*[3]; // ok void f3(int **const bar) { bar[1][1] = 5; // ok bar[1]= new int[3]; // ok bar = new int*[3]; // wrong: change int** Bad: const int ** bar Bad: int * const * bar Writing properly matters!!! 59

60 More examples … 60 int main(){ int i = 3, j = 10; int* ip = &i;
const int* ipc = ip; *ip = 5; // *ipc is now 5 ip = &j; int *const *ipp1 = &ip; // ok const int* const *ipp2 = &ip; // ok const int** ipp3 = &ipc; // ok ipp3 = &ip; // wrong: changing ipp3 // indirectly/inadvertently changes **ipp const int** ipp4 = &ip; // wrong: same reason as above, because if allowed ipp4 //could be changed later return 0; } 60


Download ppt "Pointers."

Similar presentations


Ads by Google