Você está na página 1de 4

22/02/2013

Pointers (2.7.2)

Pointer Examples
int x = 70, y = 80, z[4] = {10, 20, 30, 40 }; int *ip; ip = &x; *ip = 200; y = *ip; ip = &z[2]; *ip = *ip + 20; y = *ip+1; // int pointer ip // ip is assigned to address of x // content of ip is assigned to 200 // y is assigned to content of ip // same as *ip += 20; x : 4892 y : 4894 Z, Z[0] : 4896 Z[1] : 4898 Z[2] : 4900 Z[3] : 4902 ip : 4904
2

Pointers & Arrays

What is pointer? A variable (2 or 4 bytes long) that can hold an Address Why pointers? Sometimes the only way to express a computation Usually lead to compact and efficient code Related operators: * : can be used in two ways
In declaration : read as pointer, e.g., int *p; In accessing : read as content of, e.g., x = *p;

200 70 200 51 80 10 20 50 30 40 4900 4892 ????


3

2.7.2 & 2.7.3 (pages 55 - 60)

& : returns LValue (address) of a variable


Read as address of

Pointer Examples
int x = 100; int *p1 = &x; cout << "&x == " << &x << " << "p1 == " << p1 << " *p1 += 20; cout << "&x == " << &x << " << "p1 == " << p1 << " x == " << x << endl x == " << x << endl *p1 == " << *p1 << endl;

pointer

Pointers in Function arguments


Arguments are passed by value, thus only a copy is passed.
void swap_wrong(int x, int y) { int temp; temp = x; x = y; y = temp; } void swap(int *px, int *py) { int temp; temp = *px; *px = *py; *py = temp; }
int a = 10, b = 20; swap_wrong(a, b); cout << a << b; swap(&a, &b); cout << a << b;
4

Referencing & Dereferencing

& variable

* []

Referencing ( & ): create reference (pointer) to memory location Dereferencing (*, [ ] ): get the content of memory location
Declaration int x; Reference/Pointer/ Address/LValue &x z z+i &z[i] ptr ptr+i &ptr[i] Dereference/Variable/ Content/RValue x z[0] *(z+i) z[i] *ptr or ptr[0] *(ptr+i) ptr[i] *(&x) = 10;
6

in swap_wrong
x: y: temp: 10 20

in swap
px: 4397 py: 9643 temp:

*p1 == " << *p1 << endl;

int z[10], i;

Output
&x == 0x7fff7e60f41c x == 100 p1 == 0x7fff7e60f41c *p1 == 100 &x == 0x7fff7e60f41c x == 120

in caller:
a:4397 b:9643 10 20

int *ptr, i;

Note: x = 10;
5

p1 == 0x7fff7e60f41c *p1 == 120

Pointer Operations
The valid pointer operations are 1. Adding or subtracting a pointer and an integer (p i) 2. Assignment of pointers of the same type (p = q) 3. Subtracting or comparing two pointers in same array (p - q) 4. Assigning or comparing to zero. (p = 0) All other pointer arithmetic are illegal.

1 Addition/Subtraction with int


Used for pointing to different elements in an array
int a[6], *pa, x, i; pa = &a[2]; // same as pa = a + 2; *pa pa[0] a[2] *(pa-i) pa[-i] a[2-i] *(pa+i) pa[i] a[2+i]

1 Addition/Subtraction with int


Size of the pointed data-type is automatically taken care of. If address of a pointer (say ptr) is A then address of ptr+i is A+i*sizeof(data-type of ptr)
long *lp; int *ip; char *cp;
7832 7832

12 34 56 78 78 56 34 12
9

12 34 56 44 33 56

pa-2

pa-1

pa:

pa+1 pa+2

pa+3
7832 7833

7833

ip0x7832 *ip=0x3412 ip+10x7834 ip[1]=0x4456 ip+20x7836 ip[2]=0x5633

7833 7834 7835 7836 7837 7838 7839

lp0x7832 *lp= 0x78563412

12 34 56 44

7834 cp 7832 *cp=0x12 7835 7836 cp+2 7834 cp[2]=0x56 7837

a: a[0] a[1] a[2] a[3] a[4] a[5]

7834 7835

lp+10x7836 lp[1]= 0x12345678

pointer int pointer


7 8

22/02/2013

2-- Assignment of Pointers


Pointers of same types can be assigned.
float x = 10.5, *p = &x, *q = p;

3 Comparing/Subtraction to Pointer
The resulting type of subtracting two pointers is integer. Comparison Vs. Subtraction a<bab<0 a == b a b == 0 a>bab>0 Compared/Subtracted pointers should point in same array. Example:
/* strlen: return length of string s*/ int strlen(char *s) { char *p = s; while (*p != \0) p++; return p s; }
10

4 Comparing/Assigning to Zero
Zero is the only integer that can be assigned to a pointer Zero is the only integer that a pointer can be compared to. Use this to initialize a pointer and to check validity
char *m = 0; ... if (m != 0) { ... safe to use the pointer ... }

Pointer to void is used to hold any type of pointer


int *ip; void *vp; vp = ip; // type casting is not essential

Cannot be de-referenced without type casting.


int x = *vp; // is illegal type casting is a must int y = *((int *)vp); // is ok

NULL can be used instead of 0


pointer - pointer int
11 12

Provides some degree of Polymorphism.

Pointer Vs Array
char amessage[] = now is the time; // an array
amessage: now is the time\0

strcpy example
/* strcpy: copy t to s */ void strcpy(char *s, char *t) { int i; i = 0; while ((s[i] = t[i])!=\0) i++; }

Pointer Vs Array
Note: if you just write s=t then only the pointer will be copied, not the characters

In function argument array and pointer are same. i.e., following declaration/definition of function are equivalent
int strlen(char *str) int strlen(char str[ ])

char *pmessage
pmessage:

= now is the time; // a pointer


now is the time\0

Arguments are passed by value, thus only a copy is passed.


/* strcpy: copy t to s */ void strcpy(char *s, char *t) { while (*s++ = *t++) ; } char p[25]; char *q = Hello world; strcpy(p, q);
14

pmessage has LValue pmessage is pointer and requires 2/4 bytes for itself pmessage++ is possible pmessage=somepointer is legal amessage has no LValue amessage is a name for the starting address of the array amessage++ is illegal amessage=somepointer is illegal
13

s: t:

4397 9643

/* strcpy: copy t to s */ void strcpy(char *s, char *t) { while ((*s = *t)!=\0) { s++; t++; } }

/* strcpy: copy t to s */ void strcpy(char *s, char *t) { while ((*s++ = *t++)!=\0) ; }

4397 p: q: Hello world\0 9643

What is the effect of writing s=t?


15

strcmp example
/* strcmp: return <0 if s<t, 0 if s==t, >0 if s>t */ int strcmp(char *s, char *t) { int i; for (i = 0; s[i] == t[i]; i++) if (s[i] == \0) return 0; return s[i] t[i]; }

const and Pointers

const int w=20; int x, y;

References

const int w=20; int x, y;

const qualifier can be used with pointers in three ways: Prohibit a pointer from changing its content
const int *p1 = &w; // p1 can point to (non-)const int *p1 = 200; // invalid : content cant change p1 = &x; // OK. p1 points to x (non-const) int const *p2; // p2 and p2 is identical to

C++ reference is short hand for const pointer (* const)


int &r1 = x; // same as: int * const r1 = &x

References must be initialized at declaration and cant change Referencing and dereferencing are implicitly done by C++
r1 = r1 + 5 + w; // not for using *r1

Prohibit a pointer from changing its reference:


/* strcmp: return <0 if s<t, 0 if s==t, >0 if s>t */ int strcmp(char *s, char *t) { for ( ; *s == *t; s++, t++) if (*s == \0) return 0; return *s *t; }

Address of reference means its targets address.


cout << (&r1 == &x); // output: 1

int * const p3 = &x; // must be initialized at creation p3 = &y; // invalid: reference cant change *p3 = 123; // OK. changes value of x

Useful with functions for pass-by-reference


void swap(int &a, int &b) { int t = a; // a and b are passed by reference a = b; b = t; }
17 18

Prohibit a pointer from changing both reference & content:


const int * const p4 = &w; // must be initialized at creation & point to const int

16

22/02/2013

Dynamic Memory Management


Program image in RAM Environment variables Static Data Stack

2.15 p-89

Dynamic Memory Allocation


// Allocating array int *parr = new int[10]; delete [] parr; // Allocating data for reference struct Foo { char c1, c2; }; Foo *p = new Foo(); p->c1 = X; delete p; // explicit free // Allocating data for reference Foo &r = *new Foo(); r.c1 = X; delete &r; // explicit free
20

Pointer Anomalies
Uninitialized variable : Before storage can be used, it must be allocated.
Foo *p; p->c1 = R; // forget to initialize pointer with new // places R at some random location in memory

Can be accessed via getenv function


char *gvar = some string; int max_size = 200; int myfunc(int x) { int y = 20; x = x + y; return x * y; } int main(void) { int *px = new int; cin >> x; cout << myfunc(x); delete px; }
19

After storage is no longer needed it must be explicitly deleted otherwise memory leak results.
Foo *p = new Foo; p = new Foo; // forgot to free previous storage

Heap

After storage is deleted, it must not be used:


delete p; p->c1 = R; // result of dereference is undefined

Program code

p is called a dangling pointer.

21

Pointers Vs. Multi-dim Arrays


int m[10][20] m m is a 2D array: 200 int sized locations have been set aside 10 m[row][col] is calculated as 20row+col int *pm[10] pm is a 1D array of pointers to int. Only 10 pointers are allocated pm[i] must be initialized/allocated with code (malloc) or static initialized (like name array) int **ppm c is a pointer of pointers to int. Only 1 pointer is allocated c must be initialized/allocated with code (malloc) ppm c[i] must be initialized/allocated with code (or static initialized (like name array) Examples in next slide
20

Pointers Vs. Multi-dim Arrays

Multi-dimensional Array : Formal Param.


In function parameter only the left most dimension is unnecessary. Thus all the following are equivalent:
void func(int daytab[2][13]) { } void func(int daytab[][13]) { } void func(int (*daytab)[13]) { }

int m[3][4]; for (int r = 0; r < 3; r++) for (int c = 0; c < 4; c++) m[r][c] = (r+1)*10 + c; int *pm[3]; for (int r = 0; r < 3; r++) { pm[r] = new int[4]; for (int c = 0; c < 4; c++) pm[r][c] = (r+1)*10 + c; } int **ppm = new int *[3]; for (int r = 0; r < 3; r++) { ppm[r] = new int[4]; for (int c = 0; c < 4; c++) ppm[r][c] = (r+1)*10 + c; }
22

10 11 12 13 20 21 22 23 30 31 32 33

pm
10

The brackets in last statement is necessary since [ ] have higher precedence than *.
int (*daytab)[13] : a pointer to an array of 13 elements
0 daytab 12

int *daytab[13] : an array of 13 pointers to integers.


23

daytab[0] [1]

[12]
24

Complicated Declarations
Read C declarations using a counter-clock wise spiral Do not cross a bracket (**a[]) unless all the tokens within the bracket are finished

Complicated Declarations
char (*(*x())[5])()

Command-line Arguments

(2.11 p-79)

char ( * ( * x () ) [5] ) ()

main is called with two arguments : int argc: is the number of command-line arguments char **argv: pointer to array of strings (i.e., char *)
int main(int argc, char **argv)

int *f()

int * f ()

f is a function returning int *

x is a function returning pointer to array[5] of pointer to function returning char

echo.c invoked with: echo hello world


argc is 3 and argv is
argv [0] [1] echo\0 hello\0 world\0 0

char (*(*x[3])())[5]
int (*f)() int ( * fp ) () fp is a pointer tofunction returning int

#include <iostream> int main(int argc, char **argv) { for (int i = 1; i < argc; i++) std::cout << argv[i] << " "; std::cout << endl; }

[2] [3]

x is a array[3] of pointer to function returning pointer to array[5] of char


25 26 27

22/02/2013

Command-line Arguments
/* Processing command-line options: like abc x v */ int main(int argc, char **argv) { while (--argc > 0 && (*++argv)[0] == -) { // each option group while (c = *++argv[0]) { // for each option in the goup // process the option } } }
argv ++argv (*++argv) 0 x f r
\0

Command-line Arguments
/* Processing command-line options: like abc x v */ int main(int argc, char **argv) { while (--argc > 0 && (*++argv)[0] == -) { // each option group while (c = *++argv[0]) { // process the option } } }
argv ++argv[0] argv[0] 0 x f r
\0

Pointers to Functions
In C/C++, a function itself is not a variable But pointer to function can be created int (*comp)(void *, void *);
comp is a pointer to function that returns int and takes two void * type arguments

// for each option in the group

find.exe\0 (*++argv)[0]

find.exe\0

BEWARE: int *comp(void *, void *)


means that comp is a function that that returns int * and takes two void * type arguments

*++argv[0] -m\0

-m\0

int result = (*comp)(&x, &y)


invokes comp with parameters x and y

28

29

30

Pointer to Function : Example

Be Careful with * and ++/-* and ++ / -- are executed from right to left
char *p = XAD; char *q = p; char c;

Coercion: Storage of Values in Memory


Same memory location can be interpreted in different ways: long int
Intrepreted as 1 long int

41

43

45

47

0x41434547

Statement
c = ++*q; c = *++q; c = *q++;

q p p+1 p+1 p

Comment
Increment content of q and return new value. (*q)++; c = *q; Increment q and fetch content. q++; c = *q; fetch content of q and then increment q. i.e., c = *q; q++; Return content of q and then increment content of q. i.e. c = *q; (*q)++;

7832 7833 7834 7835

47 45 43 41
Intrepreted as 2 short int

short int 45 41 char 47 47 43

Y YAD A XAD X XAD

0x4547 0x4143

G E C A Note: All numbers in this slide are in hexadecimal system.


33

4-bytes in RAM

Intrepreted as 4 char

45 43

c = (*q)++; X YAD

The above is also true for the operator.


31 32

Higher bits stored in higher address

41

Coercion: Assignment of Pointers


Cast and then assign
int i = 0x4145, *ip = &i; char *cp = (char *)ip; cout << *cp << endl << cp[1] << endl << showbase << hex << int (*cp) << endl << int (cp[1]) << endl << *ip << endl ;
cp:8996 *cp: 78 38 *(cp+1): i:7838 7839 45 41 78 38 ip:8976
RAM bytes

Coercion: Assignment of Pointers


Cast and then assign
long int l = 0x41434547, *lp = &l; int *ip = (int *)lp; // same as int *ip = (int *)&l; char *cp = (char *)lp; // same as char *ip = (char *)&l;

Coercion: Assignment of Pointers


Cast and then assign
long int char cout int l = 0x41434547, *lp = &l; *ip = (int *)lp; *cp = (char *)lp; << *cp << *(cp+1) << *(cp+2) << *(cp+3) << *ip << *(ip+1) << *lp;

lp:8974 l:7832 E A 7833 7834 7835


Logical View

78 32 78 32 78 32

47 45 43 41

ip:8976 cp:8978

Note: lp, ip and cp are all of size 2 bytes though they are pointing to data of different sizes, 4, 2 and 1 bytes, respectively.

7832 7833 7834 7835

47 45 43 41

*cp=G *(cp+1) =E *(cp+2) =C *(cp+3) =A

7832 7833 7834 7835

47 45 43 41
*(ip+1) 0x4143 *ip 0x4547

7832 7833 7834 7835

47 45 43 41
*lp 0x41434547

hi-8bits[7839] *ip: lo-8bits [7838]

41 45
34

RAM bytes
35

RAM bytes

RAM bytes

RAM bytes
36

Você também pode gostar