Pointers Guide: Initialization, Dereferencing, Arithmetic, and More
1. What will be covered
Pointers
Pointer definition
Initialization
Dereferencing Pointers
Constant Pointer
Pointer Arithmetic's
Adding or subtracting integer from pointers.
Pointers and Arrays
Pointers as arguments
Memory Management using Pointers
new operator
delete operator
Lecture 7: Pointers 1
2. Pointers
Pointers are variables like any other type. However they
are also derived type like arrays.
Just like other variables, you need to declare pointers
before using them and there must exist one and only one
definition for each variable of type pointer.
Pointers can be used to hold “memory address ” of other
variables of a given type.
However just like, each variable has a type, pointers also
have type, like
Pointer to an int. It can be used to hold addresses of only and
only int variables (not even unsigned int)
Pointer to a char, hold addresses of only and only char
Pointer to an object of any user defined type such as say
“shape”.
Lecture 7: Pointers 2
3. Why Pointers should have type?
Why type?
Unless you would tell what type of address pointer is pointing to,
compiler would not know how to use (interpret) that pointer. Example:
If pointer to double, that means next eight bytes are holding the double in
a particular way.
If unsigned, that means two bytes, with no sign bit.
If char, means ASCII value in single byte.
To perform what is known as pointer arithmetic’s you need to know
size of element to which pointer is “ pointing”.
To be able to have compile time error checking, making your program
more robust, you need to specify type.
However language gives you freedom to cast it to pointer of most of
the other types, thus giving you all the freedom.
So, type of variable to which it is pointing is firmly attached with
all pointers.
Lecture 7: Pointers 3
4. Defining Pointers
Pointers are a powerful tool and should be used carefully.
Whenever you need to use it, you have to define them first.
Pointer have a name, just like other variables. Same naming
convention, as for variable, is used for pointers.
Name of pointer is different than the name of variable to which
they may be pointing (don’t get confused here).
Example
int *pi, *pj, *pk; // three pointers to int
// with names pi, pj and pk
char *str; // pointer to char
Here ‘*’ is used to indicate it is pointer variable and not int.
Note that * needs to be used for every variable declaration
separately.
So, int *pi, pj; /* defines two variables, pi is pointer to int
and pj is normal int variable and not a pointer */
Lecture 7: Pointers 4
5. Correct Pointer
Definitions
Correct examples of Definitions are:
double* abc; // * can be close to double or abc
double *bcd; // Ok, however you need * with every pointer.
double *cde,* def, * efg; // 3 pointers each of type pointer to double
You can defined pointer to derived or user defined types as well,
However, definition depends upon operator precedence
int *fgh[5]; // Since precedence of [] is higher than *, this is array of
// 5 pointers to int and not pointer to array of 5 ints
int (*ghi)[5]; // This is single pointer to array of 5 ints.
Similarly if say Shape is user defined type than
Shape * hij; // hij is pointer to Shape (UDT, definition of which should
// come before this definition of pointer).
We can also have pointer to pointer
int * * ijk; // ijk is pointer to (pointer to int). I.e we can store address
// of any pointer to int in ijk.
Similarly there could be pointer to pointer to pointer of a type & so on…
Lecture 7: Pointers 5
6. Wrong Pointer Definitions
Wrong Definitions of pointers are:
double abc *; // * can not be after the name
* double bcd; // * can not be before the type name.
double *cde, def; // if we want def to be pointer there
// must be a * before it
pointer * efg; // Type has to be specified (pointer is not a
keyword)
* fgh; // Error, if type is completely missing
Shape *ghi; // if Shape has not been defined so far.
int & ijk; // we cannot use & or other operators in place of *
// & means reference and not pointer
Lecture 7: Pointers 6
7. Pointer Initialization
You need to set proper values (address) to pointers just
like you set values for variables, before you can use them.
This is how you can set proper values for local and global
pointer variables
Initialize them at the time of declaration with address of a
known variable, example
int *pi=&i; /* initialized to address of i. i should only be of
type int and should already be defined or declared in the
current file. i could be local or global variable */
Here ‘&’ is acting as “address of” operator
If not initialized, it can later be assigned an address of any
variable of the same type, before using it
int *pi;
pi=&i; /* assign address. This can be done multiple time. You
may assign it the address of any other variable at any time */
Lecture 7: Pointers 7
8. Dereferencing pointers
Ok, so you have also initialized or assigned the address to
our pointer. Now what?
You can perform following actions
You can dereference the pointer to get the object to which
your pointer is pointing. Example
int *pi=&i;
(*pi)=76; // same as i=76; here * is deference and not pointer
In other words, you can use (*pi), anywhere you can use int
variables, even on left side. You don’t need (), but can be used
for clarity. I.e. you could say *pi=3*4+7;
You can perform pointer arithmetic's. Discussed later
Pointers can be used to pass arguments to function which the
functions can modify (Equivalent to Pass by reference).
Pointers are used to allocate memory at run time as per your
needs (Memory Allocation). Discussed at the end
Lecture 7: Pointers 8
9. Pointer to constant
You can define
Pointer to a const variable, as follows
const int *pi=&i; //also int const* pi
i itself need not be a const variable. It could be any normal
variable, however when referenced through pi, we cannot modify i.
Now you cannot use (*pi) to modify the contents of i. However you
can use it to access the contents of i.
(*pi)=10; // error
(*pi)++; // error
int j= (*pi)+56; // OK as we are not modifying i
You can still make pi point to another variable of type int, example
pi=&j; // ok for pointer to const variable
// Note: when assigning address you should not
// use *pi instead use pi itself.
Lecture 7: Pointers 9
10. Constant Pointer
You can also define const pointer to a variable, as
follows
int *const pi=&i; // use const after ‘*’
It must be initialized (not assigned afterwards) because we are
defining a constant pointer, which can not be assigned later on.
You can modify i using (*pi), as follows
(*pi)=10; // OK, variable is not constant
(*pi)++; // OK
However now pi cannot point to any other variable
pi=&j; // ERROR, constant pointer
Similarly we have const pointer to a const variable
const int * const pi=&i; // or int const * const pi=&i;
Now we cannot modify i through pi or assign address of any other
variable in pi. We can use it only to access value of i at any time.
(*pi)=10; // Error
(*pi)++; // Error
pi=&j; // Error
j = (*pi)+56; // OK
Lecture 7: Pointers 10
11. Pointer Arithmetic
You can add or subtract a integer from all those pointers which
are not declared const pointer, example
int *pi=&i;
pi+=10; // No compiler error, now pi is pointing to
// 10 th int’s address from the address of i
pi++; // pi is further incremented by one
--pi; // decrement pi by one.
pi=pj-j; // where pj is another pointer and j is int
Note: When performing arithmetic it is on pi and not (*pi)
You can subtract two pointers of same type to get an int,
example
int *pi=&i; *pj=&j, k;
k=pi-pj; // value of k would be int
/* it would return number of elements of pointer type and not
number of bytes */
Lecture 7: Pointers 11
12. Pointer Arithmetic
When we perform pointer Arithmetic, Compiler assumes that
the address that our pointer is pointing to belongs to array of
the type of variables to which our pointer belongs.
That is Given
int i, *pi=&i; /* compiler assumes pi contains address of an
array of int’s */
Therefore when we say pi++; Compiler changes the address in
pi so that it is now pointing to next integer, I.e. address which
is 2 bytes from the original address. (compiler does not bother
whether it is actually int or not, it simply assumes it is int and
will try to interpret that memory as int).
So, if we increase the address in double pointer by one, it now
points to next double (I.e. 8 th byte’s address from original
address)
Remember, when we are performing pointer arithmetic it is on
pointer pi and not on (*pi).
Lecture 7: Pointers 12
13. Pointer and Arrays
Pointers and Arrays go side by side. In fact array is
implemented as const pointer
When you define array variable, two things happen
A const pointer is created with the name of the array variable
Enough continuous memory is reserved (allocated) in data
segment (not on heap) and address of its first element is stored
in the array variable (in other words const array pointer is
properly initialized)
Now pointer arithmetic is used to access elements of array
Example
int arr[10]; // array of ten int’s
variable arr is actually implemented as int * const arr and
initialized
to the Address of memory allocated (10 int’s)
Now if you use, for example arr[5]; compiler would replace this
with *((arr)+(5)); This is why index start from 0 and not 1.
i.e., it would dereference the 5th address from the address of first
element, which would be address of 6th element.
Lecture 7: Pointers 13
14. Pointer and Arrays
Example continues…
Note that we cannot change the value of arr itself, but we
can use it’s value to access rest of the elements
Even in case of pointer, you can add or subtract integer
value (or variable) from a pointer and then dereference it
Compiler would simply try to access whatever is there at
the computed address as a type of that pointer
So, if you say
int *pi=&i; // initialize with address of a variable
*(pi+3)=10; // compiler would try to access 6 th and 7 th bytes
from the address of i, as variables of type int. It would not
generate any error message, if those bytes are actually
not int, or if they have not been allocated by your
program
So, it’s the responsibility of programmers to ensure that
you are accessing proper memory locations using
pointers Lecture 7: Pointers 14
15. Pointer as Arrays
So, if they have so many similarities can pointers be used with
similar notation as of array
Why not!
Example
int *pi=&i;
pi[2]=10; // same as *(pi+2)=10;
Hey but you are using address of single variable as address of
array
That’s why I said in beginning, its powerful tool, use carefully.
YES you can and no compiler errors, but surely run time errors
(even collapse of OS)
Compiler cannot differentiate between pointer to single variable
or pointer to array.
So, can array variables be used as pointer notation. Yes, as
long as you are using them as const pointer
int arr[10];
*(arr+i)=67; // same as arr[i]=67;
Lecture 7: Pointers 15
16. Pointer as function
argument
Pointers can be used as a function argument as follows:
say we want to define a function which takes pointer to int as argument
void myFunc(int * pi); // function prototype
In the function body, use pi, as if it has been properly defined &
initialized
void myFunc(int *pi) {
*pi=10; // use pi as defined and initialized pointer
}
At other places, where you need to call that function, you would need to
supply ADDRESS of VARIABLE (or address of constants if the argument
is defined as const pointer)
myFunc(&i); // Ok, whether argument is normal or const pointer
myFunc(&45); // only if argument is defined as const pointer
myFunc(i); // ERROR, supply address of int and not int itself
You may also pass pointer to int (not address of pointer to int)
int i=20,*pi;
pi= &i;
myFunc(pi); // OK, However after this call value of i would change.
myFunc(&pi); // ERROR, don’t supply address of pointer to int
Lecture 7: Pointers 16
17. Memory Management
Using pointers we can take memory management in our hand and we can
directly control lifetime of variables.
I.e. we can create variables whenever we want and destroy them after we
have used them.
Suppose, we want to create a variable in one function say f1(); and then
use them even after that function is finished. This is how we can create a
variable in function f1();
int *pi; // pi is some global pointer to int
void f1() {
pi = new int; // using operator new
// now use pi as we want, it is pointing to an unnamed int
}
Here new operator is used which work as follows
When we use expression new anytype; // anytype could be fundamental,
derived or user defined type
Than new operator allocates enough memory for one variable of type anytype
It than returns the address of the memory which is allocated. We can store
this address in pointer to anytype .
Lecture 7: Pointers 17
18. Releasing Memory
Now using that pointer (I.e. by dereferencing that pointer), we can use
the recently allocated variable as we want.
When we don’t want to use that variable any more, we can release the
allocated memory as follows
delete pi; // delete is an operator, which release memory
Deleting an earlier allocated pointer, more than once is programming
error. Not deleting it even once, though not an error, but leads to
memory leaks which could be bad if your program performs lot of memory
allocation.
Deleting a pointer which is properly initialized with address of a variable
which is not allocated by you, may not lead to run time error, but is
programming error.
int i=10, *pi=&i;
delete pi; // no runtime error but programming error
Pointers can be assigned null value
myClass *ptr; // myClass is some user defined class
ptr=0; // null pointer
delete ptr; // deleting null pointer, even multiple times, has no side
effects
Lecture 7: Pointers 18
19. Allocating Arrays
Using new operator we can even allocate more than one variable
example
int *pi = new int[40]; // allocate 40 int’s and store address of first
pi[3]=10; // int in pi so that using pi, we can use all 40 int’s
pi[39]=20; // now pi just as array of 40 int’s
Since new operator can take expression using variable, we can
dynamically allocate memory as per our requirement. Example
int size;
cout << “Enter size of char array: “;
cin >> size;
char *pd = new char[size]; // array size will be decided at run
time
We can even allocated user defined type using new operator.
Remember, that address returned by new operator is useful till
we want to use the allocated memory and so it should usually
not be stored in local pointer objects, which would be lost at the
end of that function. If so, than we would not be able to
deallocate that memory.Lecture 7: Pointers 19
20. Exercise
There would be a quiz before the next class.
Write a program which will take input of any
number of integers till –1 is entered. It will
than display each separate number that was
input along with number of times it was
input. Interaction with program should be as
follows:
Number: 34
Number: 34
Number: 45
Number: -1
Number 34 was specified 2 times
Number 45 was specified 1 times
Lecture 7: Pointers 20
21. Exercise contd…
Write a program which would make spiral matrix.
Interaction with program should be as follows.
Enter size of matrix (odd): 5
Writing matrix…
17 16 15 14 13
18 5 4 3 12
19 6 1 2 11
20 7 8 9 10
21 22 23 24 25
Can you modify the program so that it also ask for
starting direction and rotation (clockwise or
anticlockwise) and makes matrix as per that direction
and rotation.
Lecture 7: Pointers 21