Professional Documents
Culture Documents
2b. Pointers in C++
2b. Pointers in C++
Dr. K. Veningston
Department of Computer Science and Engineering
National Institute of Technology Srinagar
veningstonk@nitsri.net
Introduction to Pointers
• In C/C++,
– Entire memory is viewed as the 1-D array
– Variables generally be stored in the memory at some location.
• We use variable names for convenience
– Example: char a;
a
p &c
c ‘a’
Variable name vs. Pointer
• In C/C++,
– Example: int b;
b
Starting address of b
& operator
• & operator can be applied to anything that has a memory
address.
– You cannot apply & on register variables as they are stored on CPU
registers.
– in C, constants are not compile-time constants (i.e. always allocated
storage), so you can safely take address of a constant variable.
Address of a constant
• NOTE:
– a const variable may not need to be assigned any storage at all (i.e. The code generated using a
const variable will often be almost like you would use a literal directly. However, your source code
gets to use a meaningful name instead).
Dereferencing or indirection
• Referring to the object pointed to by the pointer.
char c1 = ‘a’;
char* p = &c1;
char c2 = *p; // c2 = ‘a’; * is the dereference operator
p &c
c1 ‘a’
How to declare a pointer?
• Note:
– Either it is an int, char or any other structure, pointer size is always same.
– Variable container size may vary, but its address is same size for all the
data structures.
• Analogy: houses are of different size, but all the houses will have same size address.
– We need to change the size of the pointer depending on the type of the
pointer
• They why do we write int *p;? --> Pointer arithmetic or Address arithmetic
– Depending on the type of element, we have same size of the pointer
How to declare a pointer?
• Dereferencing or indirection operator (*) int b;
int *p;
– & is used to get the address p = &b;
– * is for dereferencing or indirection
• Name of a pointer variable --> standing outside the memory cell
• When we apply * --> getting inside the memory cell
p b
104
100 101 102 103 104 105 106 107 108
Address Content
1000
1001
1002
1003
1004 i= 5
1005
1006
1007
1008 p = 1004
1009
1010
Example on Pointers - 1
Address Content
1000
1001
1002
1003
1004 i= 5
1005
1006
1007
1008 p = 1004
1009
1010
Example on Pointers - 2
Address Content
1000
1001 i = 10
int i = 10; 1002
1003
int *ip;
1004 ✓
double d = 3.14; 1005 ip = 1001
double *dp; 1006 X X
ip = &i; //Valid 1007
ip = &d; //Not valid 1008 d = 3.14
dp = &d; //Valid
1009
✓
1010
dp = &i; //Not valid 1011 dp = 1008
1012
1013
1014
To find
• i=?&j=?
void f(int *p, int *q){
p = q;
*p = 2;
}
int i = 0, j = 1;
int main(){
f(&i, &j);
cout << i <<“ “<< j <<endl;
return 0;
}
To find
• i=0&j=2
void f(int *p, int *q){
p = q;
*p = 2;
}
int i = 0, j = 1;
int main(){
f(&i, &j);
cout << i <<“ “<< j <<endl;
return 0;
}
Type-casting
Pointers and Arrays
• Arrays and Pointers are strongly related.
– Whatever possible with arrays, also possible with pointers
– Array name itself is like a pointer
– Ex: int a[5];
100 101 102 103 104 105 106 107 108 109 110 111 112 113
… … … …
… … … …
102
p
Pointers and Arrays
• A pointer kind of representation is machine friendly.
Address of a[2]
(a+2) = &a[2]
– &a[2] vs. &(a[2]) --> Both are same. Array subscript operation has higher
precedence over unary operator
• Ex:
100 101 102 103 104 105 106 107 108 109 110 111 112 113
int *p; … … … …
int a[5];
p = &a[0];
X a[0] a[1] a[2] a[3] a[4]
104
p++; p
How does compiler resolve that p++; should add 2 bytes?
int *p;
Parenthesis essential? No Details
Pointer p can be used as if it is an array
100 101 102 103 104 105 106 107 108 109 110 111 112 113
int *p; … … … …
int a[5];
p = &a[0]; X
a[0] a[1] a[2] a[3] a[4]
108
p++; p
p = p + 2;
Difference between Pointer and Array
• (i) A pointer is a variable, but array name is a mnemonic to the
starting address
• (ii) Operations on array and pointer variable.
– int a[5];
• a = a + 1;
• a++; Invalid
• a = p;
– int *p;
• p = p + 1;
• p++; Perfectly valid
• p = a;
Pointer Arithmetic (or) Address Arithmetic
• Valid pointer operations:
– (i) Assignment of pointers of the same type.
• If they are not of same type, we should go through typecasting.
– (ii) Adding or subtracting a pointer and an integer.
– (iii) Subtracting or comparing 2 pointers to members of the same
array.
– (iv) Assigning or comparing to 0.
(i) Assignment of pointers of the same type
• Ex 1: int *p, *q;
– p = q;
– q = p; Legal assignment
• Ex 2: int *p, a[];
– a could be treated as the pointer to integer --> p = a; //allowed
– a = p; Illegal --> a is a mnemonic, not the variable
• If we try to assign a pointer of different type, then we have to do
type casting.
– Ex: char *c;
• c = p;
Not allowed
• p = c;
typecasting
• Ex: int *p, *q;
char *c;
• Address of p, q, c are of same type and size, whether it is a pointer
to char or int.
– Still, assigning to a pointer variable has a problem.
– When we try to increment/decrement, compiler might get confused about
the scaling.
• p = p + 1; --> p = p + i * sizeof(int)
• c = c + 1; --> c = c + i * sizeof(char)
– Assigning one to another will require some casting.
• p = (int*) c;
Pointer to int Pointer to char
NOTE: In case, c is a void* pointer, typecasting is not required.
typecasting
(ii) Adding or subtracting a pointer and an integer
• We could either add an integer or subtract an integer.
100 101 102 103 104 105 106 107 108 109 110 111 112 113
Ex: … … … …
int *p;
int a[5];
p = &a[1]; a[0] a[1] a[2] a[3] a[4]
p 104
– void fun(int a[], int rows){…} (or) void fun(int* a, int rows){…} 115 115 116 117 118 119
• When passing 2D array into a function 120 120 121 122 123 124
– void fun(int arr[][5], int rows){…} (or) void fun(int (*arr)[5], int rows){…} 125 125 126 127 128 129
– We have to mention that how many columns are there in every row of the 2D 130
array. Because, that will be the size of 1 element of this 2D array.
– int arr[][5] means arr is an array of some number of elements, each element is an
array of size 5.
• void fun(int (*arr)[2][4], int rows){…}
– arr is a pointer to a 2D array of 2x4 elements each of type int.
Pointers & 2D array - Example
10
104
109
5
103
108
4
9
102
107
3
8
*(pmatrix+1)+1
101
106
2
7
100
105
1
6
*(*(pmatrix+1)+1)
matrix
*pmatrix 100
Pointers & Multi-dimensional arrays
• 3D array
– char arr[3][4][6] …
• 3 2-D array, each of which is of 7 rows 6 columns.
100 100 101 102 103 104 105
• arr points to a memory location which is a 2D array of size 4x6.
• arr + 1 will point to the 2nd 2D array of size 4x6 i.e. 124. 106 106 107 108 109 110 111
arr[0]
– We skip 24 integers. 112 112 113 114 115 116 117
• char (*p)[3][4][6] = &arr; 118 118 119 120 121 122 123
– p is a pointer to a 3D array of 3x4x6 elements each are of 124 124 125 126 127 128 129
– This subtraction will result in 1. 142 142 143 144 145 146 147
– This says that we have skipped 1 block of 4x6 integers. 148 148 149 150 151 152 153
• cout << (char*)(&arr + 1) – (char*) &arr; 154 154 155 156 157 158 159
arr[2]
160
– This subtraction will result in 24 * sizeof(char) = 24. 160 161 162 163 164 165
• arr will behave like a char* 178 178 179 180 181 182 183
• 124 – 100 = 24 i.e. these many characters lies between these 2 184
addresses.
Pointer to Function
• Like a (data) object, the code generated for a function body is
placed in memory somewhere, so it has an address.
• We can have a pointer to a function just as we can have a pointer
to an object.
• The pointer obtained by taking the address of a function can then
be used to call the function.
• Defining pointer to function: void (*foo)(int);
void (*ptr)(int);
ptr = &fun; (or) ptr = fun;
ptr(5); (or) (*ptr)(5);
You can skip asterisks * here.
Practice Question
• Displaying the array content in reverse order.