Binary World

Download Report

Transcript Binary World

C programming Language
Chapter 5:
Pointers
04 ‫ספטמבר‬
Copyright Meir Kalech
1
What is a Pointer?





A pointer is a variable that contains the address of
a variable.
A Pointer (to type) can be associated with a type.
We are familiar with: int, float, char, … types.
Each type has a comparable pointer (to) type:
int *, float *, char *, etc.
The difference: while primitive types store values,
the pointer types store addresses. For example:




int * stores an address of int.
char * stores an address of char.
float * stores an address of float.
Pointer size is 4 bytes (independently of its type).
04 ‫ספטמבר‬
Copyright Meir Kalech
2
Operators * and &
C defines two operators: & (address of) and
* (indirection) for use with pointers:

Indirection Operator * has 2 different meanings:
• Upon declaration – “I am a pointer”.
• After declaration – access the variable whose address is
held by the pointer.

Address Operator & provides the address of a variable.
04 ‫ספטמבר‬
Copyright Meir Kalech
3
Pointers Example
0
1
2
3
4
5
6
7
8
9
A
B
int1: 24
10
11
12
13
14
15
16
C
D
E
F
float1: 76.45
17
18
19
1A 1B
1C
1D
1E
1F
28
29
2A 2B
2C
2D
2E
2F
db1: 2.45633
20
21
22
23
24
25
26
27
pint: 4
30
31
32
char1:
‘a’
33
34
35
36
37
38
39
pfloat: c
3A 3B
3C
pdb: 12
40
41
42
43
44
04 ‫ספטמבר‬
45
46
3D
3E
3F
pchar: 29
47
48
49
4A 4B
4C
4D
4E
4F
Copyright Meir Kalech
void main()
{
int int1=24;
float float1=76.45;
double db1=2.45633;
char char1=‘a’;
double *pdb=&db1;
char *pchar=&char1;
int *pint;
float *pfloat;
pint = &int1;
pfloat = &float1;
}
4
Example
Swap two
integer values
through use of
pointers
void main()
{
int x=4, y=8, temp;
int *pint1,*pint2;
pint1 = &x;
pint2 = &y;
temp = *pint1;
*pint1 = *pint2;
*pint2 = temp;
}
04 ‫ספטמבר‬
Copyright Meir Kalech
5
Example
temp: 100
pint1: 250
pint2: 350
x: 200
y: 300
4
8
04 ‫ספטמבר‬
void main()
{
int x=4, y=8, temp;
int *pint1,*pint2;
pint1 = &x;
pint2 = &y;
temp = *pint1;
*pint1 = *pint2;
*pint2 = temp;
}
Copyright Meir Kalech
6
Example
temp: 100
pint1: 250
pint2: 350
200
300
x: 200
y: 300
4
8
04 ‫ספטמבר‬
void main()
{
int x=4, y=8, temp;
int *pint1,*pint2;
pint1 = &x;
pint2 = &y;
temp = *pint1;
*pint1 = *pint2;
*pint2 = temp;
}
Copyright Meir Kalech
7
Example
temp: 100
4
pint1: 250
pint2: 350
200
300
*pint1
x: 200
y: 300
4
8
04 ‫ספטמבר‬
void main()
{
int x=4, y=8, temp;
int *pint1,*pint2;
pint1 = &x;
pint2 = &y;
temp = *pint1;
*pint1 = *pint2;
*pint2 = temp;
}
Copyright Meir Kalech
8
Example
temp: 100
4
pint1: 250
pint2: 350
200
300
*pint2
*pint1
x: 200
y: 300
8
8
04 ‫ספטמבר‬
void main()
{
int x=4, y=8, temp;
int *pint1,*pint2;
pint1 = &x;
pint2 = &y;
temp = *pint1;
*pint1 = *pint2;
*pint2 = temp;
}
Copyright Meir Kalech
9
Example
temp: 100
4
pint1: 250
pint2: 350
200
300
*pint2
x: 200
y: 300
8
4
04 ‫ספטמבר‬
void main()
{
int x=4, y=8, temp;
int *pint1,*pint2;
pint1 = &x;
pint2 = &y;
temp = *pint1;
*pint1 = *pint2;
*pint2 = temp;
}
Copyright Meir Kalech
10
Example
temp: 100
4
pint1: 250
pint2: 350
200
300
x: 200
y: 300
8
4
void main()
{
int x=4, y=8, temp;
int *pint1,*pint2;
pint1 = &x;
pint2 = &y;
temp = *pint1;
pint1 = pint2;
*pint2 = temp;
}
What
happens in
this case?
04 ‫ספטמבר‬
Copyright Meir Kalech
11
Example
temp: 100
4
pint1: 250
pint2: 350
300
300
x: 200
y: 300
8
4
void main()
{
int x=4, y=8, temp;
int *pint1,*pint2;
pint1 = &x;
pint2 = &y;
temp = *pint1;
pint1 = pint2;
*pint2 = temp;
}
This is a
pointer
assignment!
04 ‫ספטמבר‬
Copyright Meir Kalech
12
Be careful
int x = 4;
int *px;
px = x;
int x = 4;
int *px;
float *pf;
pf = px;
int *px;
*px = 9;
04 ‫ספטמבר‬
Error compilation:
Cannot convert from int to int *
BUG!
Cannot convert from int * to float *
BUG!!!
px points to garbage - trying to assign
a value to memory not allocated
Copyright Meir Kalech
13
Call by Address
Passing argument by value:
the argument is copied to the local
parameter of the function.
 Passing argument by address:
only the address of the argument is
passed (a local parameter stores the
address). So the operator * enables
access to the value of the argument.

04 ‫ספטמבר‬
Copyright Meir Kalech
14
Call by Value Example
swap gets x and y
and swaps between them
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
swap_by_value
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
main
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
Copyright Meir Kalech
Address:
300
Address:
400
Address:
500
temp
num2
num1
Return address
Address:
100
Address:
200
y=5
x=3
15
Call by Value Example
Arguments passing
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
swap_by_value
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
main
Copyright Meir Kalech
Address:
300
Address:
400
Address:
500
temp
num2=5
num1=3
1024
Address:
100
Address:
200
y=5
x=3
16
Call by Value Example
temp = num1;
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
swap_by_value
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
main
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
Copyright Meir Kalech
Address:
300
Address:
400
Address:
500
temp=3
num2=5
num1=3
1024
Address:
100
Address:
200
y=5
x=3
17
Call by Value Example
num1 = num2;
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
swap_by_value
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
main
Copyright Meir Kalech
Address:
300
Address:
400
Address:
500
temp=3
num2=5
num1=5
1024
Address:
100
Address:
200
y=5
x=3
18
Call by Value Example
num2 = temp;
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
swap_by_value
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
main
Copyright Meir Kalech
Address:
300
Address:
400
Address:
500
temp=3
num2=3
num1=5
1024
Address:
100
Address:
200
y=5
X=3
19
Call by Value Example
After swap_by_value has
returned
Note that x and y
weren’t changed
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
main
Copyright Meir Kalech
Address:
100
Address:
200
y=5
x=3
20
Call by Address Example
swap gets x and y
and swaps between them
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
swap_by_address
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
main
Copyright Meir Kalech
Address:
300
Address:
600
Address:
500
temp
num2
num1
Return address
Address:
100
Address:
200
y=5
x=3
21
Call by Address Example
Arguments passing
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
swap_by_address
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
main
Copyright Meir Kalech
Address:
temp
300
Address:
num2=100
600
Address: num1=200
500
1024
Address:
100
Address:
200
y=5
x=3
22
Call by Address Example
temp = *num1;
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
swap_by_address
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
main
Copyright Meir Kalech
Address:
temp=3
300
Address:
num2=100
600
Address: num1=200
500
1024
Address:
100
Address:
200
y=5
x=3
23
Call by Address Example
*num1 = *num2;
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
swap_by_address
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
main
Copyright Meir Kalech
Address:
temp=3
300
Address:
num2=100
600
Address: num1=200
500
1024
Address:
100
Address:
200
y=5
x=5
24
Call by Address Example
*num2 = temp;
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
swap_by_address
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
main
Copyright Meir Kalech
Address:
temp=3
300
Address:
num2=100
600
Address: num1=200
500
1024
Address:
100
Address:
200
y=3
x=5
25
Call by Address Example
After swap_by_value has
returned
Note that x and y
were changed
void main()
{
int x=3, y=5;
swap_by_value(x, y);
swap_by_address(&x, &y);
}
void swap_by_value(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
}
void swap_by_address(int *num1, int *num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
04 ‫ספטמבר‬
main
Copyright Meir Kalech
Address:
100
Address:
200
y=3
x=5
26
Passing Arguments Summary Table
By value
By address (of array)
Declaration
func(type name)
func(type name[])
func(type *name)
Scope
In function
In function
Lifetime
In function
Argument
changeable
No
04 ‫ספטמבר‬
Address: lifetime only in
function
Array’s elements: original
lifetime
Address: no
Array’s elements: yes
Copyright Meir Kalech
27
Pointers and Arrays

The meaning of assigning an array to a
pointer is assigning the first array address
(by array name) into the pointer:




Scanning the array is possible by using:



int array[5];
int *parr;
parr = array; // same as parr = &array[0];
Operator []
Operator *
But first, which pointer operators available?
04 ‫ספטמבר‬
Copyright Meir Kalech
28
Pointer Arithmetic Operators


There are some arithmetic operations that
can be performed on pointers.
Add/subtract an integer to/from a pointer:
int arr[10];
int *ptr1 = arr, *ptr2;
ptr2 = ptr1 + 3; //ptr1+3*sizeof(int)
arr
100 104 108 112 116 120 124 128 132 136
? ? ? ? ? ? ? ? ? ?
ptr1: 100
04 ‫ספטמבר‬
ptr2: 112
Copyright Meir Kalech
Conclusion:
On adding an
integer to a
pointer, the new
address is
determined
according to
sizeof of the
pointed type.
29
Pointer Relational
Operators

Comparing pointers:


Two pointers can be compared if they point to the same
type.
Any pointer may be compared to the NULL (zero) pointer.
Examples:
int *p1 = NULL, *p2 = NULL;
if (p1 == p2) …
if (p1 < p2) …
if (p1 != NULL) …

A good programmer verifies the validity
of a pointer before using the indirection
operator * on it.
04 ‫ספטמבר‬
Copyright Meir Kalech
30
Operator [] and Operator *

As seen before, we may declare:
int a[100];
int *p = a;

The following expressions (in each line)
have the same meaning:






a,&a[0],p,&p[0]
*a,a[0],*p,p[0]
a+1,&a[1],p+1,&p[1]
*(a+1),a[1],*(p+1),p[1]
a+i,&a[i],p+i,&p[i]
*(a+i),a[i],*(p+i),p[i]
04 ‫ספטמבר‬
address of the 1st element
value of the 1st element
address of the 2nd element
value of the 2nd element
address of the i-th element
value of the i-th element
Copyright Meir Kalech
31
Operator [] and Operator *
So what is the difference between operator [] and
operator * ???
Perfectly
legal
int arr[100];
int *parr = arr;
arr++;
arr += 5;
Error in
compilation
parr++;
parr += 5;
Note: The array name isn’t a variable!!!
04 ‫ספטמבר‬
Copyright Meir Kalech
32
Operator ++

Given the declarations:
int k, *ptr = NULL;
int Arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
ptr = Arr;
What is the meaning of
k = *ptr++; ?

k = *ptr++ is equivalent to the following 2 statements:
 k = *ptr; ptr++;

What
 k
 k
 k
 k

Try to avoid such unreadable code, even it works!
is
=
=
=
=
04 ‫ספטמבר‬
the meaning of :
(*ptr)++;
*(ptr++);
*++ptr;
++*ptr;
Copyright Meir Kalech
33
Scanning Arrays using
Pointers
Scanning arrays using pointers is faster than
scanning them using indices. Here are 2 functions
that perform the same job.
1. Uses indices to sum the n first elements of array v:

long scan_with_indices(int v[], int n)
{
int i = 0;
// The operations
long total = 0;
while(i < n)
{
total += v[i];
++i;
}
return total;
// <
// += *(v + i*sizeof(int))
// ++
}
04 ‫ספטמבר‬
Copyright Meir Kalech
34
Scanning Arrays using
Pointers
2. Uses pointers to sum n first elements of array v.

long scan_with_pointers(int *v, int n)
{
long total = 0;
// The operations
int *save_end = v+n;
while(v < save_end)
// <
{
total += *v;
// += *(indirection)
++v;
// ++
}
return total;
}
Conclusion: Each iteration of scanning with indices involves
a multiplying action and an addition action that are not
necessary when scanning with pointers - more efficient!
04 ‫ספטמבר‬
Copyright Meir Kalech
35
Array of Pointers


Array of pointers is an array whose elements
are pointer types.
Definition:
int *arr[5];


// array of 5 int pointers
This is necessary for 2D-array handling by
pointers.
For instance:


Assume array of strings is defined. Manipulations
on the array is preferable by pointers than by
array indexing itself.
For example: reverse the order of the strings.
04 ‫ספטמבר‬
Copyright Meir Kalech
36
Array of Pointers
Example
void main()
{
char names[3][5] = {“DANA”,
”RANI”,”SHIR”};
char *pnames[3], *temp;
int i, j;
for(i=0; i<3; i++)
pnames[i] = names[i];
for(i=0,j=3-1; i<j; i++,j--)
{
temp = pnames[i];
pnames[i] = pnames[j];
pnames[j] = temp;
}
pnames: 200
names: 100
200
?
D
A N A
\0
204
?
R
A N
I
\0
208
?
S
H
I R
\0
?
temp: 300
for(i=0; i<3; i++)
printf(“%s\n”, pnames[i]);
}
04 ‫ספטמבר‬
Copyright Meir Kalech
37
Array of Pointers
Example
void main()
{
char names[3][5] = {“DANA”,
”RANI”,”SHIR”};
char *pnames[3], *temp;
int i, j;
for(i=0; i<3; i++)
pnames[i] = names[i];
for(i=0,j=3-1; i<j; i++,j--)
{
temp = pnames[i];
pnames[i] = pnames[j];
pnames[j] = temp;
}
pnames: 200
names: 100
200
100
D
A N A
\0
204
105
R
A N
I
\0
208
110
S
H
I R
\0
?
temp: 300
for(i=0; i<3; i++)
printf(“%s\n”, pnames[i]);
}
04 ‫ספטמבר‬
Copyright Meir Kalech
38
Array of Pointers
Example
void main()
{
char names[3][5] = {“DANA”,
”RANI”,”SHIR”};
char *pnames[3], *temp;
int i, j;
for(i=0; i<3; i++)
pnames[i] = names[i];
for(i=0,j=3-1; i<j; i++,j--)
{
temp = pnames[i];
pnames[i] = pnames[j];
pnames[j] = temp;
}
pnames: 200
200
100
204
105
208
110
names: 100
i
j
D
A N A
\0
R
A N
I
\0
S
H
I R
\0
?
temp: 300
for(i=0; i<3; i++)
printf(“%s\n”, pnames[i]);
}
04 ‫ספטמבר‬
Copyright Meir Kalech
39
Array of Pointers
Example
void main()
{
char names[3][5] = {“DANA”,
”RANI”,”SHIR”};
char *pnames[3], *temp;
int i, j;
for(i=0; i<3; i++)
pnames[i] = names[i];
for(i=0,j=3-1; i<j; i++,j--)
{
temp = pnames[i];
pnames[i] = pnames[j];
pnames[j] = temp;
}
pnames: 200
200
100
204
105
208
110
names: 100
i
j
D
A N A
\0
R
A N
I
\0
S
H
I R
\0
100
temp: 300
for(i=0; i<3; i++)
printf(“%s\n”, pnames[i]);
}
04 ‫ספטמבר‬
Copyright Meir Kalech
40
Array of Pointers
Example
void main()
{
char names[3][5] = {“DANA”,
”RANI”,”SHIR”};
char *pnames[3], *temp;
int i, j;
for(i=0; i<3; i++)
pnames[i] = names[i];
for(i=0,j=3-1; i<j; i++,j--)
{
temp = pnames[i];
pnames[i] = pnames[j];
pnames[j] = temp;
}
pnames: 200
200
110
204
105
208
110
names: 100
i
j
D
A N A
\0
R
A N
I
\0
S
H
I R
\0
100
temp: 300
for(i=0; i<3; i++)
printf(“%s\n”, pnames[i]);
}
04 ‫ספטמבר‬
Copyright Meir Kalech
41
Array of Pointers
Example
void main()
{
char names[3][5] = {“DANA”,
”RANI”,”SHIR”};
char *pnames[3], *temp;
int i, j;
for(i=0; i<3; i++)
pnames[i] = names[i];
for(i=0,j=3-1; i<j; i++,j--)
{
temp = pnames[i];
pnames[i] = pnames[j];
pnames[j] = temp;
}
pnames: 200
200
110
204
105
208
100
names: 100
i
j
D
A N A
\0
R
A N
I
\0
S
H
I R
\0
100
temp: 300
for(i=0; i<3; i++)
printf(“%s\n”, pnames[i]);
}
04 ‫ספטמבר‬
Copyright Meir Kalech
42
Array of Pointers
Example
void main()
{
char names[3][5] = {“DANA”,
”RANI”,”SHIR”};
char *pnames[3], *temp;
int i, j;
for(i=0; i<3; i++)
pnames[i] = names[i];
for(i=0,j=3-1; i<j; i++,j--)
{
temp = pnames[i];
pnames[i] = pnames[j];
pnames[j] = temp;
}
for(i=0; i<3; i++)
printf(“%s\n”, pnames[i]);
pnames: 200
names: 100
200
110
D
A N A
\0
204
105
R
A N
I
\0
208
100
S
H
I R
\0
Output:
SHIR
RANI
DANA
}
04 ‫ספטמבר‬
Copyright Meir Kalech
43