pointers part i (fundamentals) computer programming i lecture 12 copyright (c) 2004 by wong ya ping...

79
Pointers Pointers Part I Part I (Fundamentals) (Fundamentals) Computer Programming I Lecture Lecture 12 12 Copyright (C) 2004 by Wong Ya Ping <[email protected]> updated : ver080415(KCLee)

Upload: ashlynn-parsons

Post on 17-Jan-2016

213 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

PointersPointers

Part IPart I

(Fundamentals)(Fundamentals)

Computer Programming I

Lecture 12Lecture 12

Copyright (C) 2004 by Wong Ya Ping <[email protected]>updated : ver080415(KCLee)

Page 2: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

Lecture ObjectivesLecture Objectives

To define the basic concepts of pointers in C/C++, their declaration and use.

To illustrate the applications of pointer variables and pointer operators.

To understand the relationship between pointers and arrays.

To understand what is pointer arithmetic.

2

Page 3: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

ProblemProblem How can I write a function that returns

more than one value? How can I write a function that modifies the values pass to it as parameters? In C++, we know this can be achieve using reference variables. How about in C, which is a subset of C++?

We also know that when we pass an array to a function, the function may change the values stored in the array, but how does it work actually?

3

Page 4: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

#include <iostream>

using namespace std;

void swap( int& a, int& b ) {

int temp = a;

a = b;

b = temp;

}

int main() {

int a = 3, b = 9;

cout << a << " " << b << endl;

swap(a, b);

cout << a << " " << b << endl;

system("pause");

}

Let's consider a function that swaps two integers, in C++ we can Let's consider a function that swaps two integers, in C++ we can write the function as below:write the function as below:

3 99 3

This function uses passing-by-reference as parameter passing, there are 2 questions to be asked here:

1. What mechanism is used in this function?

2. Reference variable is a concept in C++, how does C program pass parameters for similar purposes?

output:

4

Page 5: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

'Z'

2010 2011 2012 2013 2014 2560 2561 2562 2563 2564

14368 1085.234

Before we move on, let's represent the memory of the Before we move on, let's represent the memory of the computer:computer:

memory addresses = a unique index for each bytes

a lot more memory in betweenmore memory more memory

a character occupies only one byte of memory

a 32-bits integer occupies 4 bytes

a 32-bits floating points values occupies 4 bytes

NOTE : the actual address of the data is usually determined by the computer, nevertheless, we usually put some values here as example for the purpose of illustration only.

Memory RepresentationMemory Representation

5

Page 6: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

'Z'

2010 2011

2560

1085.234

Instead of represent the whole block of memory, we may just use Instead of represent the whole block of memory, we may just use diagram below:diagram below:

only specify the first address

(We can draw it vertically as well)Sometime we may not want to draw out

actually how many bytes the data occupies, we can do just as follows:

14368

2011 1085.2342560

Even though only one box is used, it does not imply the data represented using one byte.

14368

6

Page 7: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

Likewise, we may represent a block of memory this way :

1085.234256054 432 2000 21 9998

2010 2014 2018 2022 2026

0.000322564

12.7382568

100000.02572 Again, even though only one box is used, it does not imply that the data represented is using only one byte.

Based on the way we write the example addresses, we can know each box actually represent 4 bytes. The address written here actually is the address of the first byte of the data (which is a 32-bits floating point value.)

Based on the way we write the example addresses, we can know each box actually represents 4 bytes. The address written here actually is the address of the first byte of the data (which is a 32-bits integer value.)

7

Page 8: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

2560

2632

2687

25

345.23421

These addresses are just examples for the purpose of illustration, we may omit them if it is not needed.

327

int num1 = 25;int num2 = 327;int num3;float f1 = 345.2;char ch1 = 'A';

Consider the declaration below:

'A'2432

num1

num2

num3

f1 [float]

ch1 [char]

We can write 65 here too, as this is the numerical equivalent of the character 'A‘.

These are the variable names.

We leave this out because the value is undetermined.

The actual position of where we put the addresses and variable names is not important.

We represent them as below:

For clarity, we may want to write the data type here.

8

Page 9: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

Numbers Swapping Function Numbers Swapping Function ProblemProblem

#include <iostream>

using namespace std;

void tryToSwap( int a, int b ) {

int temp;

temp = a; a = b; b = temp;

}

int main() {

int a = 3, b = 9;

tryToSwap(a, b);

cout << a << " " << b;

}

2560

2632

a

b

1432

1519

3

9

a

b

2644 temp

function tryToSwap()

function main()

Let’s consider how we can swap numbers without using references, (especially if you are using C). We can consider the program below, which obviously will not work. Let's try to trace and see what happens:

NOTE : Even though the variable names a and b are unique within each of the functions, the memory addresses are unique throughout the whole system, the actual memory are not local to the functions but accessible by all the functions if the addresses are known.

9

Page 10: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

2560

2632

3

9

a

b

1432

1519

3

9

a

b

2644 temp

function tryToSwap()

function main()

Next...

The value of variables a and b in main() are being COPIED to variables a and b of function tryToSwap()...

#include <iostream>

using namespace std;

void tryToSwap( int a, int b ) {

int temp;

temp = a; a = b; b = temp;

}

int main() {

int a = 3, b = 9;

tryToSwap(a, b);

cout << a << " " << b;

}

10

Page 11: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

2560

2632

9

3

a

b

1432

1519

3

9

a

b

2644 3 temp

function tryToSwap()

function main()

Next...

the value of variables a and variable b of function tryToSwap() are being swapped...

#include <iostream>

using namespace std;

void tryToSwap( int a, int b ) {

int temp;

temp = a; a = b; b = temp;

}

int main() {

int a = 3, b = 9;

tryToSwap(a, b);

cout << a << " " << b;

}

11

Page 12: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

2560

2632

a

b

1432

1519

3

9

a

b

2644 temp

function tryToSwap()

function main()

Next...

After the function tryToSwap() is executed, nothing happens to variables a and b of main() and their value remain unchanged.

#include <iostream>

using namespace std;

void tryToSwap( int a, int b ) {

int temp;

temp = a; a = b; b = temp;

}

int main() {

int a = 3, b = 9;

tryToSwap(a, b);

cout << a << " " << b;

}

12

Page 13: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

1432

1519

3

9

a

b

function main()

So, what do we do?It would be nice if we can do something like this:

1432

1519

Function main() says to function tryToSwap():

Hey, I have 2 values I want to swap, I am not going to merely give you the values, I am letting you know their addresses, so please get the value from those addresses, swap them and put the new values back to those memory....

The story continues.....

function tryToSwap()

13

Page 14: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

1432

1519

3

9

a

b

function main()

continues.....

Function tryToSwap() says :

Alright, let me store up these two addresses in two variables called pA and pB.

function tryToSwap()

4121

4176

1432

1519

pA

pB

14

Page 15: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

1432

1519

3

9

a

b

function main()

continues.....

Function tryToSwap() says :

Now... let me read the value in the addresses as indicated by pA and pB and copy these values into my own variable called x and y.

Then after swapping x and y, I will copy the values back to the location as indicated by pA and pB.

function tryToSwap()

4121

4176

1432

1519

pA

pB

2730

2752

x

y

2763 temp

15

Page 16: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

1432

1519

9

3

a

b

function tryToSwap()

function main()

continues.....

Function main() says to tryToSwap():

Horray, it is like magic, my value of a and b has been swapped!

Thank you.4121

4176

1432

1519

pA

pB

2730

2752

x

y

2763 temp

16

Page 17: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

Let's put the story aside first:

Let's introduce some new symbols and operators in C:

1432

a [ int ]int a;

If I want to store the address of a, what do I do?

int* p;

If I want to store an integer, I store it in a integer data type called 'int' ...but if I want to store an address, then I must have some kind of data type speciallyfor storing address.

Here it is :4324

p [ int* ]

What? Don't worry, just accept it for the time being that this is the data type for storing addresses, the type is int*.

we get...

we get...

Basics of PointersBasics of Pointers

17

Page 18: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

1432

a [ int ]

int a;int* p; 4324

p [ int* ]

If we declare this..

we get...

18

Page 19: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

1432

3 a [ int ]

int a;int* p;a = 3;p = &a;

4324

1432 p [ int* ]

Let’s assign a value of 3 to variable a. Since p is meant for storing address, we store the address of variable a into variable p.

we get...

This symbol & is called ampersand, it is an operator which returns an address (in this case, the address of variable a.)

The address of variable a is now stored here.

We now say that the value of variable p is the address of variable a.

Take note and DO NOT BE CONFUSED, since p is itself a variable, it has its own address too. In our example above :

p has a value of 1432, which is to say, p has the value of &a (i.e. address of a)

BUT &p has a value of 4324 [we are not using this for our example here]. 19

Page 20: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

p is called a pointer, just as a home address points to a physical house location, a pointer in C points to a values stored elsewhere in the computer memory, in our case, p actually points to the value of variable a. We can visualize it as follows:

1432

3 a [ int ]

4324

1432 p [ int* ]

3 a [ int ]

p [ int* ]

Very often, we will just leave out the example address as we don't really need to know its actual values.

int a;int* p;a = 3;p = &a;

20

Page 21: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

1432

3

a [ int ]

int a = 3;int* p;p = &a;

1432p [ int* ]

we get...

What can we do with pointers?Well, now we know that given the declaration:

p is a pointer pointing to the value of variable a, to access (to get the value or to change the value) the value of variable a indirectly using the pointer, we can use a special operator in C/C++ called indirection operator (or dereference operator), the symbol for the unary operator is '*' (asterisk).

p being &a;

then...*p equals to a;

Whenever we have : NOTE : This '*' has nothing to do with the '*' in the pointer declaration (as in int* p;).

21

Page 22: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

If we want to read the value pointed by p, we can do this:

int a = 3;int* p;p = &a;cout << *p << endl;cout << *p + 2 << endl;a = 10;cout << *p << endl;

3510

output:

Here we are accessing the value of variable a indirectly through the pointer, thus the '*' operator is called indirection operator.It is also called dereferencing operator as we are accessing the value by referencing another variable (which is the pointer).

22

Page 23: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

If we want to change the value pointed by p, we can do this:

int a = 3;int* p; p = &a;*p = 9;cout << a << endl;cout << *p << endl;

99

output:

1432

9

a [ int ]

1432p [ int* ]

*p = 9

23

Page 24: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

More example:

10 20 10 2032 45 32 4531 24 31 2429 24 29 24

output:#include <iostream>

using namespace std;

int main() {

int x = 10, y = 20;

int* pX;

int* pY;

pX = &x;

pY = &y;

cout << x << " " << y << " " << *pX << " " << *pY << endl;

*pX = 32; /* equals to x = 32; */

*pY = 45; /* equals to y = 45; */

cout << x << " " << y << " " << *pX << " " << *pY << endl;

x = 31;

y = 24;

cout << x << " " << y << " " << *pX << " " << *pY << endl;

*pX = *pY + 5; /* equals to x = y + 5 */

cout << x << " " << y << " " << *pX << " " << *pY << endl;

}

24

Page 25: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

More example:

10 20 10 2011 24 11 2411 24 24 2411 24 24 11

output:#include <iostream>

using namespace std;

int main() {

int x = 10, y = 20;

int* p1;

int* p2;

p1 = &x;

p2 = &y;

cout << x << " " << y << " " << *p1 << " " << *p2 << endl;

(*p1)++; /* equals to x++; */

*p2 += 4; /* equals to y+=4; */

cout << x << " " << y << " " << *p1 << " " << *p2 << endl;

p1 = p2;

cout << x << " " << y << " " << *p1 << " " << *p2 << endl;

p2 = &x;

cout << x << " " << y << " " << *p1 << " " << *p2 << endl;

}

Must have the brackets, without them it means very different thing.

You can assign one pointer to another as long as they are of the same type. p1 now also points to y.

You can always reassign a pointer to point to another variable as long as it is not a constant pointer (more on this later.)

25

Page 26: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

Warning !!!

int main(){ int *p; *p = 10;}

What's wrong with this code?

p [ int* ]

?

Where does the value 10 end up? Since we did not initialize p to point to anything, the value in p is undetermined and unpredictable, the above code may end up corrupting some crucial part of the operating system and it may hang your system. Therefore always save your programs regularly when programming with pointers, if you make some mistake, it may very well hang your whole system.

26

Page 27: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

More on Pointer DeclarationMore on Pointer Declaration

int* p;

The '*' here indicates that we declare p as a pointer. Even though the same symbol is used for the deferencing operator, they are not the same. Don't get confused.

This tells us that the memory it is pointing to contains data of type int. It affects how the dereferencing operator works and also the pointer arithmetic (to be discussed later when we discuss "pointer and array".) We can declare a pointer type which points to any data type in C/C++ including user-defined type.

27

Page 28: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

6 4.3 34.16 4.3 34.112 14.3 31.412 14.3 31.413 3.1 15.713 3.1 15.7

output:#include <iostream>using namespace std;int main() { int i = 6; float f = 4.3f; double d = 34.1; int* pI = &i; float* pF = &f; double* pD = &d; cout << i << " " << f << " " << d << endl; cout << *pI << " " << *pF << " " << *pD << endl; i *= 2; f += 10.0f; d = 31.4; cout << i << " " << f << " " << d << endl; cout << *pI << " " << *pF << " " << *pD << endl; (*pI)++; *pF = 3.1f; *pD /= 2.0; cout << i << " " << f << " " << d << endl; cout << *pI << " " << *pF << " " << *pD << endl;}

More example:

28

Page 29: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

int *p1, *p2, m, n, *q;

To declare a few pointers of the same type in one line, you can do this:

equivalent

int *p1;int *p2;int m,n;int *q;

int n;int *p = &n;

equivalent

int n;int *p;p = &n;

29

Page 30: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

int* p1, p2;equivalent

int *p1;int p2;

int* p1, p2;int *p1;int *p2;

int n;int *p = n;

int n;int *p;p = n;NOT

equivalent

The C++ compiler will give you a syntax error saying that this is invalid conversion. In C, the compiler will most likely give you a warning only.

NOT equivalent

30

Page 31: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

#include <iostream>

using namespace std;

void swap( int *pA, int *pB ) {

int temp;

temp = *pA; *pA = *pB; *pB = temp;

}

int main() {

int a=3, b=9;

swap( &a, &b );

cout << a << " " << b;

}

9 3output:

Solution to the Numbers Swapping FunctionSolution to the Numbers Swapping Function

31

Page 32: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

Passing Parameters to Function By ReferencePassing Parameters to Function By Reference

1432

1519

3

9

a

b

void swap(int* pA, int* pB){

int temp = *pA;

*pA = *pB;

*pB = temp;}

int main() {

int a=3,b=9;

swap(&a,&b);

}When function main() calls function swap(), it passes the value of &a and &b to the swap() function as input. &a is the address of variable a while &b is the address of variable b.1432 1519

Then....

32

Page 33: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

1432

1519

3

9

a

b

void swap(int* pA, int* pB){

int temp = *pA;

*pA = *pB;

*pB = temp;}

int main() {

int a=3,b=9;

swap(&a,&b);

}

4121

4176

1432

1519

pA

pB

When the function swap() is being executed, it will copy the values pass to it into its own variables as defined in its function parameter list.

That means in effect, variable pA will take the value of &a and variable pB will take the value &b, it is equivalent of stating :

then...

pA = &a;pB = &b;

Therefore...

1432 1519

33

Page 34: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

1432

1519

3

9

a

b

void swap(int* pA, int* pB){

int temp = *pA;

*pA = *pB;

*pB = temp;}

int main() {

int a=3,b=9;

swap(&a,&b);

}

4121

4176

1432

1519

pA

pB2763 3 temp

In effect, in function swap(), pA now directly points to variable a of main() and pB directly points to variable b of main(), that means:

Therefore...

*pA now will be equivalent to variable a in main(), and

*pB now will be equivalent to variable b in main().

Continues...

temp = *pA is equivalent to

temp = a (of main())

34

Page 35: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

1432

1519

9

9

a

b

void swap(int* pA, int* pB){

int temp = *pA;

*pA = *pB;

*pB = temp;}

int main() {

int a=3,b=9;

swap(&a,&b);

}

4121

4176

1432

1519

pA

pB2763 3 tempContinues...

Continues...

*pA = *pB is equivalent to

a = b in main()

35

Page 36: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

1432

1519

9

3

a

b

void swap(int* pA, int* pB){

int temp = *pA;

*pA = *pB;

*pB = temp;}

int main() {

int a=3,b=9;

swap(&a,&b);

}

4121

4176

1432

1519

pA

pB2763 3 temp

Therefore, the values are now swapped!

continues...

*pB = temp is equivalent to

b = 3 in main()

36

Page 37: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

37

p == &n

*p == n

Summary so far:Summary so far:

Whenever we have :

then : True.

*p == n

p == &n

Whenever we have :

then : True?

Assuming p is a pointer (type [int *]) and n is an integer (type is [int])

Page 38: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

38

p == &n

*p == n

Whenever we have :

then : True.

*p == n

p == &n

Whenever we have :

then :

Not necessarily true!Why?

Assuming p is a pointer (type [int *]) and n is an integer (type is [int])

Page 39: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

39

p == &n

*p == n

Whenever we have :

then :

*p == n

p == &n

Whenever we have :

then :

1432

3

n [ int ]

1432p [ int* ]

1560

3

x [ int ]

1560p [ int* ]

1432

3

n [ int ]

Assuming p is a pointer (type [int *]) and n is an integer (type is [int])

Page 40: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

40

*&p == p

&*p == p

The following are always true:

Assuming p is a pointer (type [int *]) and n is an integer (type is [int])

*&n == n

1432

3

n [ int ]

1432p [ int* ]

1320

&*n == n not valid

Page 41: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

41

#include <stdio.h>void swap( int* pA, int* pB ) { int temp = *pA; *pA = *pB; *pB = temp;}

void main() { int a=3,b=9; swap(&a,&b); printf("a = %d, b = %d\n",a,b);}

Parameters passing by address:

NOTE: We refer to this as "parameters passing by reference", strictly speaking, there is no such thing as pass-by-reference in C (many books actually got this wrong!), but there is in C++.

In C, strictly speaking, everything is exclusively pass-by-value, in the above case, the value is an address, therefore it is called "pass-by-address", sometime we say that we simulate "pass-by-reference" using this.

In C++, pass-by-reference using reference is preferred over using pointers as it is more straight forward and less error-prone.

Copies the address of b and assigns this address as the value of pointer pB.

Page 42: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

42

const int n = 3;int* p;p = &n;

Pointers and ConstantsPointers and Constants

Pointer to Constant

Valid?

n is a constant.

Page 43: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

43

const int n = 3;int* p;p = &n;

Not valid !!

const int n = 3;int* p;p = &n;*p = 8;

consider :

Here, we attempt to change the value of n, BUT n is a constant!

Therefore, a pointer of type [int *] CANNOT point to a value of type [const int].

What if I just want to read (using a pointer) the value of the constant integer without changing its value?

INVALID

Page 44: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

44

int z = 1;const int n = 3;const int* p;p = &n;

*p = 5;z = *p + 3;

p = &z;*p = 10;z = 10;

Pointer p has the type [const int *].

VALID. A pointer of type [const int *] can be used to point to a variable of type [const int].

INVALID: A pointer of type [const int *] CANNOT be used to MODIFY the value it is pointing to.

VALID. A pointer of type [const int *] CAN be used to READ the value it is pointing to.

VALID. A pointer of type [const int *] CAN be used to point to a variable of type [int], even though the integer is not a constant.Take note, p itself is NOT constant.

CONCLUSION : A pointer of type [const int *] is a Read-Only Pointer.

VALID. Even though we cannot modify z via the pointer, z still can be modify by other means since it is not a constant.

Page 45: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

45

int m, n;int * const p = &n;

*p = 10;

n = 5;p = &m;

Constant Pointerp has a type [int * const] and this means it is a constant pointer, the value it is pointing to is not constant, but p itself is a constant and cannot be changed.

p must be initialized, just as any constant variable must be initialized.

VALID. The value pointed by p is not constant, also it is VALID because the type of p is not [const int *].

VALID. because n is not a constant.

INVALID: A pointer of type [int * const] is a constant pointer and CANNOT be modified (cannot be reassigned to point to another variable).

Page 46: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

46

int m, n;const int * const p = &n;

*p = 10;

n = 5;p = &m;

p has a type [const int * const] and this means it is a constant pointer, the value it is pointing to also IS a constant.

p must be initialized, just as any constant variable must be initialized.

INVALID: A pointer of type [const int * const] is a constant pointer and CANNOT be modify (cannot be reassigned to point to another variable).

Constant Pointer to Constant =

VALID. Even though we cannot modify n via the pointer, n can still be modified by other means since it is not a constant.

INVALID: A pointer of type [const int * const] CANNOT be used to MODIFY the value it is pointing to.

pointer to constant +

constant pointer

Page 47: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

47

Summary of Pointers and Constants

Constant Pointer

To Constant

Constant Pointer

Pointer To

Constant

const int * const

int * const

const int *

const int * const p = &n;

orint const * const p = &n;

int * const p = &n;

const int * p; p = &n;

orint const * p; p = &n;

Assuming n and m is an integer (type is [int])

Name Data Type Sample Declaration

Must

Must

Optional

Need Initialization?

Continues…

NOTE: Here we use int as example, it is valid for other data type as well.

Page 48: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

48

const int * const p = &n;

orint const * const p = &n;

int * const p = &n;

const int * p; p = &n;

orint const * p; p = &n;

Sample Declarations

No

No

No

n must be constant?

from previous page...

Valid

Invalid

Valid

Invalid

Invalid

Valid

Invalid

Valid

Invalid

If n is a constant, is the sample declaration

valid?

Can p be reassigned

usingp = &m?

Is :*p = 3;

valid?

Page 49: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

49

const int * const p = &n;

The data it is pointing to is constant, thus *p = 3; is not valid. The data type

of the data it is pointing to.

This is a pointer.

The pointer itself is constant, thus p = &m; is not valid.

Need initialization if pointer is constant.

Page 50: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

50

More on Pointer TypeMore on Pointer Type

int* p;

If a pointer is simply a variable that contains an address value, why do we need to specify the data type before the '*' symbol? What is the purpose?

float* p;char* p;

Page 51: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

51

NOW, p1 and p2 point to the same memory address, why is it that the values dereferenced by *p1 and *p2 are different?

int n = 132000;

int* p1 = &n;short* p2 = reinterpret_cast<short*> ( &n ); cout << "p1=" << p1 << " " << "p2=" << p2 << endl;cout << "*p1=" << *p1 << " " << "*p2=" << *p2 << endl;

First Purpose:Pointers p1 and p2 both point to the location of where n is being stored. However, p1 has type [int*] and p2 has type [short*].

p1=0x1ff3 p2=0x1ff3*p1=132000 *p2=928

output:

Address value displayed in hexadecimal

NOTE: type [short] is same with type [short int]

We can't use static_cast here because type [int*] is not related to type [short*], any conversion will not be portable and platform dependent. To force conversion, we use reinterpret_cast, which is non-portable and non-safe.

Page 52: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

52

p1 is a pointer of type [int*], the dereference operator '*' will interpret *p1 as a value of type [int] which can be constructed using 4 bytes since it takes 4 bytes to store a int in our compiler. Therefore it will read 4 bytes starting from address 1FF3 and interpret it as: 0 x 2^24 + 2 x 2^16 + 3 x 2^8 + 160 = 132000!

On the other hand, p2 is a pointer of type [short*], the dereference operator '*' will interpret *p2 as a value of type [short] which can only be constructed using 2 bytes in our compiler, therefore it will read 2 bytes starting from address 1FF3 and interpret it as: 3 x 2^8 + 160 = 928!

160

3

21FF3

1FF2

1FF3

1FF4

1FF5

1FC0

n [int]

p2[short*]

1FF3

1FA0

p1[int*]

Explanation of the First Purpose:

int n = 132000;

int* p1 = &n;short* p2 = reinterpret_cast<short*> ( &n ); cout << "p1="<<p1<<" "<<"p2="<<p2<<endl;cout << "*p1="<<*p1<<" "<<"*p2="<<*p2<<endl; 01FF6

Page 53: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

53

Therefore, the First Purpose is:

int* p;

The pointer data type determined how the dereference ('*') operator is interpreted, it simply states how the pointer should interpret the memory it is pointed to and how many bytes should be used to interpret the value, the pointer is simply the address of the starting memory location of the data pointed to, the actual value of the data may need to be constructed using more bytes starting from that address.

float* p;char* p;

Page 54: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

54

int* p;

The Second Purpose has something to do with what we called Pointer Arithmetic. See the next section.

float* p;char* p;

Second Purpose:

By The Way: We are declaring p to be a derived type based on a fundamental type. Here int, char and float are fundamental types, other fundamental types are void, double, long double as well as signed and unsigned char, short and long. Here the derived type we are declaring is a pointer, other derived types are constant, array, function and structure.

Page 55: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

55

Pointers and ArraysPointers and ArraysThe Subscript Operator ( Operator [ ] )

Observe that the pointer p behaving just like the array n — Why?

int n[5] = {1,4,3,8,7};int *p;p = n;

cout << n[0] << " " << n[1] << " " << n[2] << endl;cout << p[0] << " " << p[1] << " " << p[2] << endl;

p[0]=43; p[1]=82; p[2]=58;

cout << n[0] << " " << n[1] << " " << n[2] << endl;cout << p[0] << " " << p[1] << " " << p[2] << endl;

1 4 31 4 343 82 5843 82 58

output:

What does this mean?

Page 56: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

56

int n[5] = {1,4,3,8,7};int *p;p = n;

cout <<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;

p[0] = 43; p[1] = 82; p[2] = 58;

cout <<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;

Since the name of the array is actually the address of the first element in the array and we have assigned the same address value to pointer p, pointer p now behave and can be used just like an array.

Assigns the value of n (which is the address of the first element of the array) to p.

1

4

3

81100

1100

1104

1108

1112

3664

p[ int* ]

1100

2650

n[ int[5] ]

The name of the array is actually a constant pointer pointing to the address of the first element in the array!

71116

n[0][int]

n[1][int]

n[2][int]

n[3][int]

n[4][int]

Page 57: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

57

int n[5] = {1,4,3,8,7};int *p;p = n;

p == &n[0]

Therefore, given:

the following are always true:

p[i] == n[i]*p == n[0]

ORint n[5] = {1,4,3,8,7};int *p;p = &n[0];

Page 58: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

58

*p == p[0]; p == &p[0];

Also, given any pointer p:

the following are always true:

Page 59: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

59

int n[5] = {1,4,3,8,7};int *p;p = &n[2];

cout <<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;p[0] = 43; p[1] = 82; p[2] = 58;cout <<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;

Observe that the pointer p is still behaving just like an array, but this time the array it is simulating seems to start only at element n[2].

1 4 33 8 71 4 4343 82 58

output:

Now p is pointing at the address of the element 2 of the array n.

Page 60: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

60

int n[5] = {1,4,3,8,7};int *p;p = &n[2];

cout <<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;p[0]=43; p[1]=82; p[2]=58;cout <<n[0]<<" "<<n[1]<<" "<<n[2]<<endl;cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;

now: p[0] is equivalent to n[2], p[1] is equivalent to n[3], p[2] is equivalent to n[4], p[i] is equivalent to n[i + 2].

1

4

3

81108

3664

p[ int* ]

1100

2650

n[ int[5] ]

7

n[0][int]

n[1][int]

n[2][int]

n[3][int]

n[4][int]

1100

1104

1108

1112

1116

Page 61: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

61

int n[] = { 222, 333, 444 };int *p1, *p2, i;p1 = &n[1];p2 = p1 + 1;

cout << reinterpret_cast<int> (p2) - reinterpret_cast<int> (p1);

Pointer Addition and Subtraction

1

output:

?What should be the output? Is it 1?

Page 62: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

62

int n[] = { 222, 333, 444 };int *p1, *p2, i;p1 = &n[1];p2 = p1 + 1;

cout << reinterpret_cast<int> (p2) - reinterpret_cast<int> (p1);

4

output:

The answer is 4 in our compiler, the answer may vary if you are using different platform (for example, you will get 2 in TCLite). BUT most likely the answer is NOT 1. WHY?

OK. We will come back to this question later, let's just put it aside for awhile.

Page 63: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

63

Remember that given a pointer, we can always treat the pointer as if it is an array starting at the memory it is pointed to. The data type of each elements in this "simulated" array will be determined by the actual pointer type.

In the above example, we can see that whenever we add a number to the pointer, we are actually making the pointer to move a certain number of position in the simulated "array".

int n[] = {1,4,3,8,7,2,5,9};int *p;p = &n[1]; cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;p++; cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;p+=2; cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;p--; cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;p-=3; cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;

4 3 83 8 77 2 58 7 21 4 3

output:

Consider:

Page 64: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

64

Here we do the similar thing as in the previous slide, here we do not change the value of the pointer p (that is, pointer p always points at the same memory address), instead we dereference the memory location which is a certain number of elements relative to the pointer p.

int n[] = {1,4,3,8,7,2,5,9 };int *p;p = &n[1];cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;cout << *p << endl;cout << *(p+1) << endl;cout << *(p+2) << endl;

cout <<p[3]<<" "<<p[4]<<endl;*(p+3) = 23;*(p+4) = 76;cout <<p[3]<<" "<<p[4]<<endl;

4 3 84387 223 76

output:

Consider:

Page 65: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

65

Consider:

1

4

3

8

1104

1100

1104

1108

1112

3862

p[ int* ]

1100

2650

n[ int[6] ]

71116

n[0][int]

n[1][int]

n[2][int]

n[3][int]

n[4][int]

21120n[5][int]

p+1

p+2

You would notice by now, if you add 1 to a pointer, it only means moving 1 position (that is 1 element of the array) in the "simulated" array the pointer is pointing to, BUT the memory address actually increases by 4 in the above example!

int n[] = {1,4,3,8,7,2 };int *p;p = &n[1];cout <<p[0]<<" "<<p[1]<<" "<<p[2]<<endl;cout << *p << endl;cout << *(p+1) << endl;cout << *(p+2) << endl;

cout <<p[3]<<" "<<p[4]<<endl;*(p+3) = 23;*(p+4) = 76;cout <<p[3]<<" "<<p[4]<<endl;

Page 66: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

66

int n[] = {1,4,3,8,7,2 };int *p = &n[1];

1

4

3

8

1104

3862

p[ int* ]

1100

2650

n[ int[6] ]

7

p[0][int]

p[1][int]

p[2][int]

p[3][int]

2 p[4][int]

p+1

p+2

REMEMBER:

Given:

p+i will point to the array element i position relative to p.

p+i does NOT mean add i to the address value of p. The exact increment of the address value is equals :

i x sizeof(datatype).

The Second Purpose (mentioned earlier) of the pointer data type is in order to know the size of each element of the "simulated" array so that the calculation for the actual memory location can be achieved given a relative position in the array.

1100

1104

1108

1112

1116

1120

Page 67: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

67

Back to the earlier question:

int n[] = { 222, 333, 444 };int *p1,*p2, i;p1 = &n[1];p2 = p1 + 1;

cout << reinterpret_cast<int> (p2) - reinterpret_cast<int> (p1) << endl;

cout << p2 - p1 << endl;

41

output:

Pointer Arithmetic : + and - operator operates on the relative position of each element in the array

Numerical Arithmetic : Since both address values have been type-casted as int values, the arithmetic operator (minus operator in this case) here operates on the actual numerical address values of the addresses.

Page 68: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

68

Another conclusion we can draw from this:

p + i &p[i]equivalent

*(p + i) p[i]equivalent

Given a pointer or an array p of any data type:

i is an offset from the pointer p.

Thus also: p == &p[0] *p == p[0]

Page 69: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

69

If ptr is declared as :

datatype * ptr;

then,

(ptr + i) points to the calculated location of:

ptr plus numerically i * sizeof(datatype)

Page 70: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

70

In fact in C/C++ :

n[i] i[n]

equivalent

*(n+i)

equivalent

The subscript operator is commutative (that is a+b is always equal to b+a), this is actually valid, but it is rather peculiar. Do not use this!

Page 71: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

71

*(p+i) *p+iNOT

equivalent

*p++ (*p)++NOT

equivalent

Page 72: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

72

Major difference between pointer and array:

int m[] = {3,1,4,6,5,3 };int n[] = {1,4,3,8,7,2 };int *p;

p = &m[1];

cout << *p << endl;cout << *(p+1) << endl;*(p+3) = 23;

cout << *n << endl;cout << *(n+1) << endl;*(n+3) = 23;

n = &m[1];

Valid.

INVALID: Because n is similar to a constant pointer and you cannot change the address values of n.

Page 73: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

73

Arrays and Function Calls

#include <iostream>using namespace std;

int arraySum( int array[], int size ){ int sum = 0; for (int i = 0; i < size; i++) sum += array[i]; return sum;}

int main(){ int m[] = {1,5,4,3,2}; int sum; sum = arraySum( m, 5 ); cout << sum;system("pause");}

Only the name of the array is passed into the function, in fact, it is the address of the first element of the array is being passed into the function.

Instead of writing int array[] in the parameter list, we can also write it as int* array. This means that the function simply accept an address. In fact, even if we write int array[] the compiler always convert it to int * array. However, you should write int array[] for clarity if you are really expecting an array.

It should be clear by now: why the values of the array can be changed when the array is being passed into a function. The reason is that, it is the address of the first element that is being passed.

Example:

Page 74: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

74

ExamplesExamples

#include <iostream>

using namespace std;

int myStrLen( char str[] ) {

int i;

for (i = 0; str[i] != '\0'; i++)

{ //empty

}

return i;

}

int main() {

char str[] = "hello world";

cout << myStrLen( str );

}

11

output:

To write our own function to compute the length of a C-string, this is one possible solution:

Iterates the pointer p through every element in the C-string (array of char) until the '\0' is found.

Page 75: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

75

#include <iostream>

using namespace std;

int myStrLen( char str[] ) {

char *p;

for (p = str; *p != '\0'; p++)

{ //empty

}

return p - str;

}

int main() {

char str[] = "hello world";

cout << myStrLen( str );

}

Iterates the pointer p through every element in the C-string (array of char) until the '\0' is found.

11

output:

Improved version:

How does this improve the previous version?

Page 76: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

76

int myStrLen( char str[] ) {

int i;

for (i=0; str[i] != '\0'; i++)

{ //empty

}

return i;

}

Need to evaluate this, str[i] is evaluated as *(str+i).

int myStrLen( char str[] ) {

char *p;

for (p = str; *p != '\0'; p++)

{ //empty

}

return p - str;

}

First version: Improved version:

Incrementing a pointer is much more efficient.

Page 77: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

77

#include <iostream>using namespace std;

int myStrCmp( char s1[], char s2[] ){ int i = 0; while (true) { if(s1[i] != s2[i]) return s1[i] - s2[i]; if(s1[i] == '\0' && s2[i] == '\0') return 0; i++; }}

int main() { char str1[] = "good"; char str2[] = "afternoon"; char str3[] = "morning"; char str4[] = "morning"; cout << myStrCmp( str1, str2 ) << endl; cout << myStrCmp( str2, str3 ) << endl; cout << myStrCmp( str3, str4 ) << endl;}

6-120

output:

To write our own function to compare C-strings, this is one possible solution:

Page 78: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

78

#include <iostream>using namespace std;

int myStrCmp( char s1[], char s2[] ){ char *p1 = s1, *p2 = s2; while (true) { if(*p1 != *p2) return *p1 - *p2; if(*p1 == '\0' && *p2 == '\0') return 0; p1++; p2++; }}

int main() { char str1[] = "good"; char str2[] = "afternoon"; char str3[] = "morning"; char str4[] = "morning"; cout << myStrCmp( str1, str2 ) << endl; cout << myStrCmp( str2, str3 ) << endl; cout << myStrCmp( str3, str4 ) << endl;}

6-120

output:

Improved version:

KC Lee:

*p1 – *p2 == ‘g’ – ‘a’

KC Lee:

*p1 – *p2 == ‘g’ – ‘a’

Page 79: Pointers Part I (Fundamentals) Computer Programming I Lecture 12 Copyright (C) 2004 by Wong Ya Ping updated : ver080415(KCLee)

79

Next Lecture

In the next lecture, we will learn:

– Pointers and Dynamic Arrays

It is very IMPORTANT that you make sure you understood this lecture before

coming to the next lecture.