pointers: part i. why pointers? - low-level, but efficient manipulation of memory - dynamic objects ...

28
Pointers: Part I

Post on 22-Dec-2015

233 views

Category:

Documents


0 download

TRANSCRIPT

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!

100100…… ……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!

100100…… …… 10241024 ……Memory address: 1024 10032

……1020

Integer a Pointer p

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”

100100…… …… …… ……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

1001008888 …… 10241024 ……Memory address: 1024 10032

……1020

a p

int a = 100;

int* p = &a;

cout << a << " " << &a <<endl;

cout << p << " " << &p <<endl;

Result is:

100 1024

1024 10032

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 (*),

1001008888 …… 10241024 ……Memory address: 1024 10032

……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 <iostream> using namespace std;int main (){

int value1 = 5, value2 = 15; int* p1;int* p2; p1 = &value1; // p1 = address of value1p2 = &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 Exampleint 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 Usagevoid 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&

int& b a; 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.

1000

1012

1016

1004

1008

#include <iostream>Using namespace std;

void main (){// Demonstrate array name is a pointer constantint a[5];cout << "Address of a[0]: " << &a[0] << endl << "Name as pointer: " << a << endl;

}

/* result:Address of a[0]: 0x0065FDE4Name as pointer: 0x0065FDE4*/

Array name is a pointer constant

Result is:

2

2

2

#include <iostream>

Using namespace std;

void main(){

int a[5] = {2,4,6,8,22};

cout << *a << " "

<< a[0] << " "

<< *(&a[0]);

..."

} //main

2

4

8

6

22a[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 <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

22a[4]

a[0]

a[2]a[1]

a[3]

a p

a

Array name as pointer

2

2

Multiple Array PointersBoth a and p are pointers to the same array.

2 2

4 4

#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];

...

}

2

4

8

6

22a[4]

a[0]

a[2]

a[1]

a[3]

p

P[0]

A[0]

Pointer ArithmeticGiven a pointer p, p+n refers to the element that is

offset from p by n positions.

2

4

8

6

22

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)

24

86

22

a

a + 2

a + 4a + 3

a + 1a[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