7/30/2019 Playing With Pointers
1/105
Save Trees, Dont take printouts 1
Playing with Pointers
Sandeep
Jain
Digitally signed by Sandeep Jain
DN: cn=Sandeep Jain, o, ou,
c=IN
Date: 2010.05.29 01:57:11 +05'30'
7/30/2019 Playing With Pointers
2/105
Save Trees, Dont take printouts2
What is a pointer?Answer 1
I dont know why are you asking me?
Answer 2
A Variable
That stores address
Of another variable
7/30/2019 Playing With Pointers
3/105
Save Trees, Dont take printouts3
Basics & - address of operator
&x address of x
* - dereferencing operatoror indirection operator
*x value at x
7/30/2019 Playing With Pointers
4/105
Save Trees, Dont take printouts4
Basicsint X = 10;
10X:
1000
printf(Value of X = %u, X); 10
printf(Address of X = %u, &X); 1000
printf(Value at address of X = %u,*(&X)); 10
7/30/2019 Playing With Pointers
5/105
Save Trees, Dont take printouts5
Basicsint X;
X:
1000
X = 101;
101X:
1000
int *P;
p:
2000
P = &X;1000P:
2000
int
int*
Here X is an int
Here P is a pointer to int
7/30/2019 Playing With Pointers
6/105
Save Trees, Dont take printouts6
Basics
101X:
1000
1000P:
2000
Hence we say that
P points to X
7/30/2019 Playing With Pointers
7/105Save Trees, Dont take printouts7
Basicsint **Q;
Q:
3000
Q = &P;2000Q:
3000
int**
Here Q is a pointer to pointer to int
OR
Q is a pointer to int pointer
OR
Q is a pointer to int*
7/30/2019 Playing With Pointers
8/105Save Trees, Dont take printouts8
Basics
101X:
1000
1000P:
2000
SO now,
Q points to P
&
P points to X
2000Q:
3000
7/30/2019 Playing With Pointers
9/105Save Trees, Dont take printouts9
Basicsprintf(Value of X = %u, X); 101
printf(Value of P = %u, P); 1000
printf(Value at value of P = %u, *P); 101
printf(Value of Q = %u, Q); 2000
printf(Value at value of Q = %u, *Q); 1000
printf(Value at value at value of Q = %u, **Q); 101
Therefore,
X == *P AND P == *Q AND X == **Q
7/30/2019 Playing With Pointers
10/105Save Trees, Dont take printouts10
Pointer declarations int X1;
X1 is an int
int* X2;
X2 is an int pointer
int *X2;
*X2 is an int
hence X2 is an int pointer
7/30/2019 Playing With Pointers
11/105Save Trees, Dont take printouts11
Quiz time int* X1, X2, *X3;
What are X1, X2, X3?a) X1, X2 are int* & X3 is an int**
b) X1, X3 are int* & X2 is an int
c) *X3 cause compiler error,otherwise X1, X2 are int*
B is correct
7/30/2019 Playing With Pointers
12/105Save Trees, Dont take printouts12
Pointer declarations * is associated with the variable name & not
the data type
Thus the declaration: int* X1, X2, *X3;is equivalent to: int *X1, X2, *X3;
orint *X1;
int X2;
int *X3;
7/30/2019 Playing With Pointers
13/105Save Trees, Dont take printouts13
Pointer declarations We can define our own type as INTPTR
So we can write declarations such as INTPTR x, y, z;
Such that x, y, z are all of type int*
We have two optionsA.
#define INTPTR int*B. typedef int* INTPTR;
B is correct
7/30/2019 Playing With Pointers
14/105Save Trees, Dont take printouts14
Pointer declarations #define INTPTR int*
INTPTR x, y, z; After preprocessing the above statement
becomes
int* x, y, z;
i.e. x is an int* & y, z are int
Not exactly what we had in mind
7/30/2019 Playing With Pointers
15/105Save Trees, Dont take printouts15
Pointer declarations
typedef int* INTPTR;
INTPTR x, y, z;
Since typedef defines a type, the abovedeclaration is equivalent to:
INTPTR x;INTPTR y;
INTPTR z;
Thus x, y, z all are of type pointer to int
7/30/2019 Playing With Pointers
16/105Save Trees, Dont take printouts16
Pointer arguments
When do we need pointer type arguments?
A function can return only ONE value per call.
Pointers are used when we need to get more thanone values to be returned after a call.
When we want a function, to be able to modifythe contents of variables local to the callingfunction.
7/30/2019 Playing With Pointers
17/105Save Trees, Dont take printouts
17
Pointer arguments
Consider the function:int sumAB(int A, int B)
{int s = A+B;
return s;
}
We want a function sumAndDiffAB whichreturns both sum and difference
7/30/2019 Playing With Pointers
18/105Save Trees, Dont take printouts
18
Pointer arguments
The solution is:int sumAndDiffAB(int A, int B)
{
int s = A + B;
int d = A B;
return s;
return d;}
7/30/2019 Playing With Pointers
19/105Save Trees, Dont take printouts
19
Pointer arguments
The CORRECT solution is:void sumAndDiffAB(int A, int B,
int *sum, int *diff){
*sum = A + B;
*diff = A B;
}
7/30/2019 Playing With Pointers
20/105Save Trees, Dont take printouts
20
Pointer arguments
Consider the following sequence of execution:
1. int main()
2. {
3. int x=10, y=20, sum;
4. sum = sumAB(x, y);
5. }
6. int sumAB(int A, int B)
7. {
8. int s= A + B;
9. return s;
10. }
10x: 20y:
sum:
7/30/2019 Playing With Pointers
21/105Save Trees, Dont take printouts
21
Pointer arguments
Consider the following sequence of execution:
1. int main()
2. {
3. int x=10, y=20, sum;
4. sum = sumAB(x, y);
5. }
6. int sumAB(int A, int B)
7. {
8. int s= A + B;
9. return s;
10. }
10x: 20y:
sum:
7/30/2019 Playing With Pointers
22/105
Save Trees, Dont take printouts22
Pointer arguments
Consider the following sequence of execution:
1. int main()
2. {
3. int x=10, y=20, sum;
4. sum = sumAB(x, y);
5. }
6. int sumAB(int A, int B)
7. {
8. int s= A + B;
9. return s;
10. }
10x: 20y:
sum:
10A: 20B:
7/30/2019 Playing With Pointers
23/105
Save Trees, Dont take printouts23
Pointer arguments
Consider the following sequence of execution:
1. int main()
2. {
3. int x=10, y=20, sum;
4. sum = sumAB(x, y);
5. }
6. int sumAB(int A, int B)
7. {
8. int s= A + B;
9. return s;
10. }
10x: 20y:
sum:
10A: 20B:
30S:
7/30/2019 Playing With Pointers
24/105
Save Trees, Dont take printouts24
Pointer arguments
Consider the following sequence of execution:
1. int main()
2. {
3. int x=10, y=20, sum;
4. sum = sumAB(x, y);
5. }
6. int sumAB(int A, int B)
7. {
8. int s= A + B;
9. return s;
10. }
10x: 20y:
sum:
10A: 20B:
30S:
7/30/2019 Playing With Pointers
25/105
Save Trees, Dont take printouts25
Pointer arguments
Consider the following sequence of execution:
1. int main()
2. {
3. int x=10, y=20, sum;
4. sum = sumAB(x, y);
5. }
6. int sumAB(int A, int B)
7. {
8. int s= A + B;
9. return s;
10. }
10x: 20y:
30sum:
7/30/2019 Playing With Pointers
26/105
Save Trees, Dont take printouts26
Pointer arguments
Consider the following sequence of execution:
1. int main()
2. {
3. int x=10, y=20, sum, diff;
4. sumAndDiffAB(x, y, &sum, &diff);
5. }
6. void sumAndDiffAB(int A, int B, int*s, int *d)
7. {
8. *s = A + B;
9. *d = A - B;
10. }
10x:
1000
20y:
2000
sum:
3000
diff:
4000
7/30/2019 Playing With Pointers
27/105
Save Trees, Dont take printouts27
Pointer arguments
Consider the following sequence of execution:
1. int main()
2. {
3. int x=10, y=20, sum, diff;
4. sumAndDiffAB(x, y, &sum, &diff);
5. }
6. void sumAndDiffAB(int A, int B, int*s, int *d)
7. {
8. *s = A + B;
9. *d = A - B;
10. }
10x:
1000
20y:
2000
sum:
3000
diff:
4000
10A:
5000
20B:
6000
3000s:
7000
4000d:
8000
7/30/2019 Playing With Pointers
28/105
Save Trees, Dont take printouts28
Pointer arguments
Consider the following sequence of execution:
1. int main()
2. {
3. int x=10, y=20, sum, diff;
4. sumAndDiffAB(x, y, &sum, &diff);
5. }
6. void sumAndDiffAB(int A, int B, int*s, int *d)
7. {
8. *s = A + B;
9. *d = A - B;
10. }
10x:
1000
20y:
2000
30sum:
3000
diff:
4000
10A:
5000
20B:
6000
3000s:
7000
4000d:
8000
7/30/2019 Playing With Pointers
29/105
Save Trees, Dont take printouts29
Pointer arguments
Consider the following sequence of execution:
1. int main()
2. {
3. int x=10, y=20, sum, diff;
4. sumAndDiffAB(x, y, &sum, &diff);
5. }
6. void sumAndDiffAB(int A, int B, int*s, int *d)
7. {
8. *s = A + B;
9. *d = A - B;
10. }
10x:
1000
20y:
2000
30sum:
3000
-10diff:
4000
10A:
5000
20B:
6000
3000s:
7000
4000d:
8000
7/30/2019 Playing With Pointers
30/105
Save Trees, Dont take printouts30
Pointer arguments
Consider the following sequence of execution:
1. int main()
2. {
3. int x=10, y=20, sum, diff;
4. sumAndDiffAB(x, y, &sum, &diff);
5. }
6. void sumAndDiffAB(int A, int B, int*s, int *d)
7. {
8. *s = A + B;
9. *d = A - B;
10. }
10x:
1000
20y:
2000
30sum:
3000
-10diff:
4000
10A:
5000
20B:
6000
3000s:
7000
4000d:
8000
7/30/2019 Playing With Pointers
31/105
Save Trees, Dont take printouts31
Pointer arguments
The swap function:
1. int main()
2. {
3. int x=10, y=20;
4. swap(x, y);
5. }
6. void swap(int A, int B)
7. {
8. int T = A;
9. A = B;
10. B = T;
11. }
10x: 20y:
7/30/2019 Playing With Pointers
32/105
Save Trees, Dont take printouts32
Pointer arguments
The swap function:
1. int main()
2. {
3. int x=10, y=20;
4. swap(x, y);
5. }
6. void swap(int A, int B)
7. {
8. int T = A;
9. A = B;
10. B = T;
11. }
10x: 20y:
10A: 20B:
7/30/2019 Playing With Pointers
33/105
Save Trees, Dont take printouts33
Pointer arguments
The swap function:
1. int main()
2. {
3. int x=10, y=20;
4. swap(x, y);
5. }
6. void swap(int A, int B)
7. {
8. int T = A;
9. A = B;
10. B = T;
11. }
10x: 20y:
10A: 20B:
10T:
7/30/2019 Playing With Pointers
34/105
Save Trees, Dont take printouts34
Pointer arguments
The swap function:
1. int main()
2. {
3. int x=10, y=20;
4. swap(x, y);
5. }
6. void swap(int A, int B)
7. {
8. int T = A;
9. A = B;
10. B = T;
11. }
10x: 20y:
20A: 20B:
10T:
7/30/2019 Playing With Pointers
35/105
Save Trees, Dont take printouts35
Pointer arguments
The swap function:
1. int main()
2. {
3. int x=10, y=20;
4. swap(x, y);
5. }
6. void swap(int A, int B)
7. {
8. int T = A;
9. A = B;
10. B = T;
11. }
10x: 20y:
20A: 10B:
10T:
7/30/2019 Playing With Pointers
36/105
Save Trees, Dont take printouts36
Pointer arguments
The swap function:
1. int main()
2. {
3. int x=10, y=20;
4. swap(x, y);
5. }
6. void swap(int A, int B)
7. {
8. int T = A;
9. A = B;
10. B = T;
11. }
10x: 20y:
20A: 10B:
10T:
7/30/2019 Playing With Pointers
37/105
Save Trees, Dont take printouts37
Pointer arguments
The correct swap function:
1. int main()
2. {
3. int x=10, y=20;
4. swap (&x, &y);
5. }
6. void swap (int *A, int *B)
7. {8. int T = *A;
9. *A = *B;
10. *B = T;
11. }
10x:
1000
20y:
2000
7/30/2019 Playing With Pointers
38/105
Save Trees, Dont take printouts38
Pointer arguments
The correct swap function:
1. int main()
2. {
3. int x=10, y=20;
4. swap (&x, &y);
5. }
6. void swap (int *A, int *B)
7. {8. int T = *A;
9. *A = *B;
10. *B = T;
11. }
10x:
1000
20y:
2000
1000A:
3000
2000B:
4000
7/30/2019 Playing With Pointers
39/105
Save Trees, Dont take printouts39
Pointer arguments
The correct swap function:
1. int main()
2. {
3. int x=10, y=20;
4. swap (&x, &y);
5. }
6. void swap (int *A, int *B)
7. {8. int T = *A;
9. *A = *B;
10. *B = T;
11. }
10x:
1000
20y:
2000
1000A:
3000
2000B:
4000
10T:
5000
7/30/2019 Playing With Pointers
40/105
Save Trees, Dont take printouts40
Pointer arguments
The correct swap function:
1. int main()
2. {
3. int x=10, y=20;
4. swap (&x, &y);
5. }
6. void swap (int *A, int *B)
7. {8. int T = *A;
9. *A = *B;
10. *B = T;
11. }
20x:
1000
20y:
2000
1000A:
3000
2000B:
4000
10T:
5000
7/30/2019 Playing With Pointers
41/105
Save Trees, Dont take printouts41
Pointer arguments
The correct swap function:
1. int main()
2. {
3. int x=10, y=20;
4. swap (&x, &y);
5. }
6. void swap (int *A, int *B)
7. {8. int T = *A;
9. *A = *B;
10. *B = T;
11. }
20x:
1000
10y:
2000
1000A:
3000
2000B:
4000
10T:
5000
7/30/2019 Playing With Pointers
42/105
Save Trees, Dont take printouts42
Pointer arguments
The correct swap function:
1. int main()
2. {
3. int x=10, y=20;4. swap (&x, &y);
5. }
6. void swap (int *A, int *B)
7. {8. int T = *A;
9. *A = *B;
10. *B = T;
11. }
20x:
1000
10y:
2000
1000A:
3000
2000B:
4000
10T:
5000
7/30/2019 Playing With Pointers
43/105
Save Trees, Dont take printouts43
Pointers & const
Consider these two variables int X = 10;
int *P = &X;
There are 3 cases1. X is constant
2. P is constant3. Value pointed by P is
constant
10X:
1000
1000P:
2000
7/30/2019 Playing With Pointers
44/105
Save Trees, Dont take printouts44
Pointers & const
Consider following: int X1 = 10, Y1 = 20;
X1 = 15; Y1 = 25; // Ok
const int X2; // Error
const int X2 = 10, Y2 = 20;
X2 = 20; Y2 = 30; // Error
int *Pi;
Pi = &X1; Pi = &Y1; *Pi = 50; // OK
Pi = &X2; Pi = &Y2; // Error
7/30/2019 Playing With Pointers
45/105
Save Trees, Dont take printouts45
Pointers & const
Continued const int *Pci;
Pci = &X1; Pci = &Y1; // OK
Pci = &X2; Pci = &Y2; // OK
*Pci = 50; // Error
int * const Cpi; // Error
int * const Cpi = &X1;
int * const Cpi = &X2; // Error
Cpi = &Y1; //Error
*Cpi = 20; //OK
7/30/2019 Playing With Pointers
46/105
Save Trees, Dont take printouts46
Pointers & const
Continued const int * const Cpci; Error
const int * const Cpci = &X1; OK
const int * const Cpci = &X2; OK
const int * const Cpci = &Y1; OK
const int * const Cpci = &Y2; OK
Cpci = &X2; Error *Cpci = 50; Error
7/30/2019 Playing With Pointers
47/105
Save Trees, Dont take printouts47
Pointer arithmetic
Addition
We can add integers to a pointer.
We cannot add two pointers E.g. P + 2, P + I, P++
Subtraction
We can subtract integers from pointer
We can subtract one pointer from another provided theyare of same type
P 1, P I, P1 P2, P--
7/30/2019 Playing With Pointers
48/105
Save Trees, Dont take printouts48
Pointer arithmetic
Multiplication & Division operations are not allowedon pointers.
Increment or Decrement operations on a pointer,make it point to the immediate next or previouselement respectively.
When we subtract one pointer from another we getthe number of elements in between.
7/30/2019 Playing With Pointers
49/105
Save Trees, Dont take printouts49
Break: sizeof operator
Consider Declarations
int i, *pi, **ppi;
char ch;
char *s1 = "Hello"; char s2[50] = "Hello";
char s3[] = "Hello";
char s4[] = {H, E, L,
L, O};
int ai1[10]; int ai2[] = {1, 2, 3};
Note: s1, s2, s3 are strings
but s4 is just an array
4
4
4 4
4
4
1 4
4
1
sizeof(10)
sizeof(int)
sizeof(i)
sizeof(pi)
sizeof(ppi)
sizeof(*pi)
sizeof(ch)
sizeof(A)
sizeof(s1)
sizeof(*s1)
7/30/2019 Playing With Pointers
50/105
Save Trees, Dont take printouts50
Break: sizeof operator
50
1
1 6
5
4
3 40
12
sizeof(s2)
sizeof(s2[0])
sizeof(*s2)
sizeof(s3)
sizeof(s4)
sizeof(Ram)
sizeof(OK)
sizeof(ai1)
sizeof(ai2)
Consider Declarations
int i, *pi, **ppi;
char ch;
char *s1 = "Hello"; char s2[50] = "Hello";
char s3[] = "Hello";
char s4[] = {H, E, L,
L, O};
int ai1[10]; int ai2[] = {1, 2, 3};
Note: s1, s2, s3 are strings
but s4 is just an array
7/30/2019 Playing With Pointers
51/105
Save Trees, Dont take printouts51
Break: sizeof operator
The sizeof operator does not evaluate the
expression passed as argument
It only evaluates the type of the expression
i.e. sizeof(I++) will return 4 but it wont
increment I;
7/30/2019 Playing With Pointers
52/105
Save Trees, Dont take printouts52
Pointers & Arrays
Some common array declarations int A[5] = {10, 20, 30, 40, 50};
char B[4] = Ram;
char C[]={R, A, M};
B: R a m \0
2000 2001 2002 2003
B[0] B[1] B[2] B[3]
C: R A M
3000 3001 3002
C[0] C[1] C[2]
A: 10 20 30 40 50
1000 1004 1008 1012 1016
A[0] A[1] A[2] A[3] A[4]
7/30/2019 Playing With Pointers
53/105
Save Trees, Dont take printouts53
Pointers & Arrays
Accessing array elements int A[5] = {10, 20, 30, 40, 50};
int *p1 = A; // May give warning
int *p2 = &A[0]; We generally access elements as A[i], P1[i]
A[i] == i[A] == *(A + i) == *(i + A)
Infact all such expression are converted to *(A + i)
form, even *P1 becomes *(P1 + 0)
A: 10 20 30 40 50
1000 1004 1008 1012 1016
A[0] A[1] A[2] A[3] A[4]
1000p1:
2000
1000p2:
3000
7/30/2019 Playing With Pointers
54/105
Save Trees, Dont take printouts54
Pointers & Arrays
What does A represent? A is an array
If we print A we get the address of the first element of the
array. i.e. printf(%u,a); 1000
A is also called a constant pointer in the sense that theaddress associated with an array is always constant.
So, A++ or ++A gives compiler error unlike p1++ or p2++
A: 10 20 30 40 50
1000 1004 1008 1012 1016
A[0] A[1] A[2] A[3] A[4]
1000p1:
2000
1000p2:
3000
7/30/2019 Playing With Pointers
55/105
Save Trees, Dont take printouts55
Pointers & Arrays
How will A[2] be evaluated? Since A is an array of int so the scale
factor is sizeof(int)
A[2] == *(A + 2) = *(1000 + 2*sizeof(int)) *(1008) == 30
Similarly p1[2] or p2[2] will result in 30
A: 10 20 30 40 50
1000 1004 1008 1012 1016
A[0] A[1] A[2] A[3] A[4]
1000p1:
2000
1000p2:
3000
7/30/2019 Playing With Pointers
56/105
Save Trees, Dont take printouts56
Pointers & Arrays
Array elements as arguments
Rule 1: There is no way we can pass all elements ofthe array in one go. However we can pass individualelements one-by-one.
Rule 2: Using the the array itself as an argumentactually passes the address of its first element.
Note:Array elements are always stored in contiguous memorylocations
7/30/2019 Playing With Pointers
57/105
Save Trees, Dont take printouts57
Pointers & Arrays
Passing 1-D array as argument1. int main()
2. {
3. int A[5] = {1, 2, 3, 4, 5};4. display(&A[0]);
5. }
6. void display(int *a, int count)
7. {
8. int i;9. for(i=0; i
7/30/2019 Playing With Pointers
58/105
Save Trees, Dont take printouts58
Pointers & Arrays
Passing 1-D array as argument1. int main()
2. {
3. int A[5] = {1, 2, 3, 4, 5};4. display(&A[0], 5);
5. }
6. void display(int *a, int c)
7. {
8. int i;9. for(i=0; i
7/30/2019 Playing With Pointers
59/105
Save Trees, Dont take printouts59
Pointers & Arrays
Passing 1-D array as argument1. int main()
2. {
3. int A[5] = {1, 2, 3, 4, 5};4. display(&A[0], 5);
5. }
6. void display(int *a, int c)
7. {
8. int i;9. for(i=0; i
7/30/2019 Playing With Pointers
60/105
Save Trees, Dont take printouts60
Pointers & Arrays
Passing 1-D array as argument1. int main()
2. {
3. int A[5] = {1, 2, 3, 4, 5};4. display(&A[0], 5);
5. }
6. void display(int *a, int c)
7. {
8. int i;9. for(i=0; i
7/30/2019 Playing With Pointers
61/105
Save Trees, Dont take printouts61
Pointers & Arrays
Dynamic allocation of 1-D array1. int i,*P;
2. P = (int*)malloc(sizeof(int)*5);
3. for(i=0; i
7/30/2019 Playing With Pointers
62/105
Save Trees, Dont take printouts62
Pointers & Arrays
Dynamic allocation of 1-D array1. int i,*P;
2. P = (int*)malloc(sizeof(int)*5);
3. for(i=0; i
7/30/2019 Playing With Pointers
63/105
Save Trees, Dont take printouts63
Pointers & Arrays
Dynamic allocation of 1-D array1. int i,*P;
2. P = (int*)malloc(sizeof(int)*5);
3. for(i=0; i
7/30/2019 Playing With Pointers
64/105
Save Trees, Dont take printouts64
Pointers & Arrays
Dynamic allocation of 1-D array1. int i,*P;
2. P = (int*)malloc(sizeof(int)*5);
3. for(i=0; i
7/30/2019 Playing With Pointers
65/105
Save Trees, Dont take printouts65
Pointers & Arrays
Dynamic allocation of 1-D array1. int i,*P;
2. P = (int*)malloc(sizeof(int)*5);
3. for(i=0; i
7/30/2019 Playing With Pointers
66/105
Save Trees, Dont take printouts66
Pointers & Arrays
Dynamic allocation of 1-D array1. int i,*P;
2. P = (int*)malloc(sizeof(int)*5);
3. for(i=0; i
7/30/2019 Playing With Pointers
67/105
Save Trees, Dont take printouts 67
Quiz time
Ifint a[5] = {1, 2, 3, 4, 5};
int *p = &a[0];
Then what will be the value of the followingexpressions and p after evaluation of eachexpression? Assuming a == 1000. ++*p
*++p
*p++
(*p)++
7/30/2019 Playing With Pointers
68/105
Save Trees, Dont take printouts 68
2-D Arrays
Double trouble
7/30/2019 Playing With Pointers
69/105
Save Trees, Dont take printouts 69
2-D Arrays
Also called Array of Arrays
E.g.int A[2][3]={1, 2, 3,
4, 5, 6};
What is A?
A two element array of typeint[3]
What is A[0] or A[1]? A three element array of type int
A: 1 2 3 4 5 6
3000 3004 3008 3012 3016 3020
0 1 2
A: 1 2 3 0
4 5 6 1
The actual storage:
7/30/2019 Playing With Pointers
70/105
Save Trees, Dont take printouts 70
2-D Arrays
Hence, A == 3000
A[0] == 3000
A[1] == 3012
sizeof(A) == 24
sizeof(A[0]) == 12
sizeof(A[0][0]) == 4A: 1 2 3 4 5 6
3000 3004 3008 3012 3016 3020
The actual storage:
0 1 2
A: 1 2 3 0
4 5 6 1
7/30/2019 Playing With Pointers
71/105
Save Trees, Dont take printouts 71
Break: Special cases
When we create an array: int A[5] = {1, 2, 3, 4, 5};
Whenever we use A it is replaced by the address oft he first element or the so called base address
However when,
A is used as argument in sizeof operator it returns
t he t otal number of byt es allocated Address of operator (&) is applied on A we get the
address of t he ent ire array & not the firstelement. Thou the two numerical values may be
same
7/30/2019 Playing With Pointers
72/105
Save Trees, Dont take printouts 72
Break: Special cases
For e.g. int A[5] = {1, 2, 3, 4, 5};
int B[2][3] = { {1, 2, 3}, {4, 5, 6} };
Assume A begins at 1000 & B at 2000
sizeof(A) = 20 and sizeof(B) = 24
sizeof(B[0]) = 12 and sizeof(B[1]) = 12
A + 1, &A + 1 A + 1 = 1004, &A + 1 = 1020
B + 1, &B + 1, &B[0] + 1
B + 1 = 2012, &B + 1 = 2024, &B[0][0] + 1 = 2004
7/30/2019 Playing With Pointers
73/105
Save Trees, Dont take printouts 73
2-D Arrays
What happens when we writeA[1][2]?
It is converted to pointer notation.
(*(A + 1))[2] *(*(A + 1) + 2)
*(*(3000 + 1*sizeof(int[3])) + 2)
*( *(3000 + 1*12) + 2)
*(3012 + 2*sizeof(int))
*(3012 + 2*4)
*(3020) == 6
Similar conversion is performed forhigher dimensions
A: 1 2 3 4 5 6
3000 3004 3008 3012 3016 3020
The actual storage:
0 1 2
A: 1 2 3 0
4 5 6 1
7/30/2019 Playing With Pointers
74/105
Save Trees, Dont take printouts 74
2-D Arrays
Pointers for 2-D array int *P1[2];
P1 is an array of 2
elements of type pointer toint
int (*P2)[3];
P2 is a pointer to an array
of 3 elements of type int
What is sizeof(p1) &sizeof(p2)?
8 & 4 respectively
A: 1 2 3 4 5 6
3000 3004 3008 3012 3016 3020
The actual storage:
0 1 2
A: 1 2 3 0
4 5 6 1
P1
1000 1004
P2:
2000
7/30/2019 Playing With Pointers
75/105
Save Trees, Dont take printouts 75
2-D Arrays
Pointers for 2-D array int *P1[2];
P1 is an array of 2
elements of type pointer toint
int (*P2)[3];
P2 is a pointer to an array
of 3 elements of type int
What is sizeof(p1) &sizeof(p2)?
8 & 4 respectively
P1[0] = &A[0][0];
P1[1] = &A[1][0];
P2 = &A[0];
A: 1 2 3 4 5 6
3000 3004 3008 3012 3016 3020
The actual storage:
0 1 2
A: 1 2 3 0
4 5 6 1
P1 3000 3012
1000 1004
P2: 3000
2000
7/30/2019 Playing With Pointers
76/105
Save Trees, Dont take printouts 76
2-D Arrays
Pointers for 2-D array int **P3;
P3 is a pointer to a pointer to int
P3 is a pointer to an int pointer
What is sizeof(p3)?
4
P3 = (int**)malloc(2*sizeof(int*));
P3[0] = &A[0][0];
P3[1] = &A[1][0];
P3:
4000
int**
7/30/2019 Playing With Pointers
77/105
Save Trees, Dont take printouts 77
2-D Arrays
Pointers for 2-D array int **P3;
P3 is a pointer to a pointer to int
P3 is a pointer to an int pointer
What is sizeof(p3)?
4
P3 = (int**)malloc(2*sizeof(int*));
P3[0] = &A[0][0];
P3[1] = &A[1][0];
5000 5004
P3: 5000
4000
int**
int*
7/30/2019 Playing With Pointers
78/105
Save Trees, Dont take printouts 78
2-D Arrays
Pointers for 2-D array int **P3;
P3 is a pointer to a pointer to int
P3 is a pointer to an int pointer
What is sizeof(p3)?
4
P3 = (int**)malloc(2*sizeof(int*));
P3[0] = &A[0][0];
P3[1] = &A[1][0];
3000 3012
5000 5004
P3: 5000
4000
int**
int*
7/30/2019 Playing With Pointers
79/105
Save Trees, Dont take printouts 79
2-D Arrays
Evaluate P1[1][2] *( *(P1 + 1) + 2)
*( *(1000 + 1*sizeof(int*)) + 2)
*( *(1000 + 1*4) + 2)
*( *(1004) + 2)
*( 3012 + 2*sizeof(int) )
*( 3012 + 2*4 ) *(3020)
6
7/30/2019 Playing With Pointers
80/105
Save Trees, Dont take printouts 80
2-D Arrays
Evaluate P2[1][2] *( *(P2 + 1) + 2)
*( *(3000 + 1*sizeof(int[3]) ) + 2)
*( *(3000 + 1*12) + 2)
*( *(3012) + 2)
*( 3012 + 2*sizeof(int))
*( 3012 + 2*4) *(3020)
6
7/30/2019 Playing With Pointers
81/105
Save Trees, Dont take printouts 81
2-D Arrays
Evaluate P3[1][2] *( *(P3 + 1) + 2)
*( *(5000 + 1*sizeof(int*) ) + 2)
*( *(5000 + 1*4) + 2)
*( *(5004) + 2)
*( 3012 + 2*sizeof(int))
*( 3012 + 2*4) *(3020)
6
7/30/2019 Playing With Pointers
82/105
Save Trees, Dont take printouts 82
Dynamic allocation
Assume a data type ALPHA
To create an array of type ALPHA having N
elements we write
ALPHA *P;
P = (ALPHA*)malloc(N*sizeof(ALPHA));
This is the general syntax to allocate memorydynamically
7/30/2019 Playing With Pointers
83/105
Save Trees, Dont take printouts 83
Dynamic allocation
Let us declare an 4x5 array dynamically
Step 1: Its a 2-D structure so we take a double
pointerint **P;
Step 2: We want 4 rows of 5 integers eachP = (int**) malloc(4*sizeof(int*));
Step 3: Each row is to be associated with an arrayof 5 integersfor(i=0; i
7/30/2019 Playing With Pointers
84/105
Save Trees, Dont take printouts 84
Dynamic allocation
1. int **P;
2. P = (int**) malloc(4*sizeof(int*));
3. for(i=0; i
7/30/2019 Playing With Pointers
85/105
Save Trees, Dont take printouts 85
Dynamic allocation
1. int **P;
2. P = (int**) malloc(4*sizeof(int*));
3. for(i=0; i
7/30/2019 Playing With Pointers
86/105
Save Trees, Dont take printouts 86
Dynamic allocation
1. int **P;
2. P = (int**) malloc(4*sizeof(int*));
3. for(i=0; i
7/30/2019 Playing With Pointers
87/105
Save Trees, Dont take printouts 87
Dynamic allocation
A Better view:
2000 3000
2004 4000
2008 5000
2012 6000
P: 2000
1000
int** int*1 2 3 4 5
3000 3004 3008 3012 3016
int
11 12 13 14 15
4000 4004 4008 4012 4016
int
21 22 23 24 25
5000 5004 5008 5012 5016
int
31 32 33 34 35
6000 6004 6008 6012 6016
int
7/30/2019 Playing With Pointers
88/105
Save Trees, Dont take printouts 88
Dynamic allocation
Evaluate P[2][3] *( *(P + 2) + 3)
*( *(2000 + 2*sizeof(int*) ) + 3)
*( *(2000 + 2*4) + 3)
*( *(2008) + 3)
*( 5000 + 3*sizeof(int))
*( 5000 + 3*4) *(5012)
24
7/30/2019 Playing With Pointers
89/105
Save Trees, Dont take printouts 89
Quiz time
Write code to allocate 2-D array such thatALL elements are stored contiguously
2000 100
2004 120
2008 140
2012 160
P: 2000
1000
int** int* 1 2 . . 6 . . 11 . . 16 . . 19 20
100 104 . . 120 . . 140 . . 160 . . 172 176
int
7/30/2019 Playing With Pointers
90/105
Save Trees, Dont take printouts 90
Dynamic allocation
Dangling pointer
When a pointer variable continues to point to somede-allocated memory.
Dangling pointer may cause segment related run-time errors. The famous segmentation fault
Memory leakage
When there exists no pointer or reference to adynamically allocated memory area.
May limit the programs capabilities
Both are e.g. of bad programming practices
7/30/2019 Playing With Pointers
91/105
Save Trees, Dont take printouts 91
Break: Declarations
int ***P1;
int *P2[5];
int (*P3)[5];
P1 is a pointer to
pointer to pointer to
int
P2 is an array of 5elements of type
pointer to int
P3 is a pointer to an
array of 5 elementsof type int
7/30/2019 Playing With Pointers
92/105
Save Trees, Dont take printouts 92
Break: Declarations
int (*P4)[4][5];
int *P5[2][3];
int *(*P6)[2][3];
P4 is a pointer to an
array of 4 elements
of type array of 5
elements of type int P5 is an array of 2
elements of type
array of 3 elements
of type int pointer P6 is a pointer to an
array of 2 elements
of type array of 3
elements of type int*
7/30/2019 Playing With Pointers
93/105
Save Trees, Dont take printouts 93
Break: Declarations
int *F1();
int (*F2())[4];
int (*F3())[3][4];
int (*F4)(char);
F1 is function
returning int pointer
F2 is a function
returning pointer toarray of 4 elements of
type int
F3 is a function
returning pointer to a
3x4 array of type int
F4 is a pointer to
function taking char
and returning int
7/30/2019 Playing With Pointers
94/105
Save Trees, Dont take printouts 94
Quiz time
Dynamically allocate memory for storingtriangular arrays.
Note: Using the regular 2-D array wastes halfof the memory.
7/30/2019 Playing With Pointers
95/105
Save Trees, Dont take printouts 95
3-D Arrays
I dont know how to teach these.
7/30/2019 Playing With Pointers
96/105
Save Trees, Dont take printouts 96
3-D Arrays
A small revision:
For 1-D array
int A[n] int *A
For 2-D array int A[m][n]
int *A[m]
int (*A)[n]
int **A
For 3-D Arrays int A[x][y][z]
int *A[x][y]
int **A[x]
int ***A
int (*A)[y][z]
int* (*A)[y]
7/30/2019 Playing With Pointers
97/105
Save Trees, Dont take printouts 97
Pointer return types
Write a function that returns an array of size5 with its elements initialized to 0.
Answer 1int* func1()
{
int A[5] = {0};
return &A[0];}
7/30/2019 Playing With Pointers
98/105
Save Trees, Dont take printouts 98
Pointer return types
Answer 2int* func2()
{
static int A[5] = {0};
return &A[0];
}
7/30/2019 Playing With Pointers
99/105
Save Trees, Dont take printouts 99
Pointer return types
Answer 3int* func3()
{
int i, *A = malloc(5*sizeof(int));
for(i=0; i
7/30/2019 Playing With Pointers
100/105
Save Trees, Dont take printouts 100
Pointer return types
Analyzing the answers
Answer 1
Segmentation fault. Why? The address returned is address of deallocated
memory.
Answer 2
You cannot use this function more than once. Why? Static variables are allocated only once and remain
there forever. This may cause data corruption.
7/30/2019 Playing With Pointers
101/105
Save Trees, Dont take printouts 101
Pointer return types
Analyzing the answers
Answer 3
Correct answer. Why? Each time this function is called, a fresh block of 20
bytes is allocated. Unlike Answer 1 this memory isnot de-allocated because it uses dynamic allocation.And dynamically allocated memory can only beEXPLICITLY de-allocated using free.
Thus,
No Segmentation fault.
No Data corruption.
7/30/2019 Playing With Pointers
102/105
Save Trees, Dont take printouts 102
Some more e.g.
char S1[] = Hello world;
char *S2 = Hello world;
char *S3; S1 = Ram; // Error
S1 is an array and thus its address
is constant
S2 = Ram; // OK
S1[0] = X; // OK
7/30/2019 Playing With Pointers
103/105
Save Trees, Dont take printouts 103
Some more e.g.
S2[0] = X; // Error
S2 is a pointer to constant char
scanf(%s, S1); // OK
scanf(%s, S2); // Error
Reason is same as above
scanf(%s, S3); // Error
Causes Segmentation fault because we
never allocated memory for S3. So it
may point to an inaccessible
location.
7/30/2019 Playing With Pointers
104/105
Save Trees, Dont take printouts 104
References
Pointers in C
Kanetkar
C Programming Language Ritchie
7/30/2019 Playing With Pointers
105/105
Thank You