Professional Documents
Culture Documents
Chapter-12
Pointers
Introduction
Before pointers one should understand about address of memory blocks.
Consider the declaration:
int i=5;
This tells compiler:
1) to reserve a memory space of two bytes
2) to associate a name i (name of block)
3) to assign 5 as a content
i
5
65524
Name of location
called variable
Memory location or
memory block
Value at location
or content
Address of
memory block
Up till now we never used address of variable, but from now we will use it to access
memory location.
main()
{
int i=5;
printf(\n %d ,i);
printf(\n %u ,&i);
printf(\n %d ,*&i);
}
Remember:
1. We cannot store anything in &i as &i is not a variable, it is the way to represent
address of block i.
2. We can collect the address of i (&i) in another variable. Lets say i and j are two
variables and we want to store address of i in j. we can do this by the following
statement:
j=&i;
3. Remember j is not an ordinary variable like any other integer variable.
4. j is a variable which contains the address of another variable
5. A compiler would provide a separate space in memory for this variable j.
6. As the j is also a variable and it requires a separate space, it is obvious that it has
some address also (location number).
7. We cant use j in program without declaring it. And since j is a variable, which
contains the address of i, it is declared as
int *j;
8. This special declaration tells the compiler that j will be used to store the address
of an integer value. In other words j points to an integer.
main()
{
int i = 5, *j;
j= &i;
&i);
j);
&j);
*&j);
i);
*(&i));
*j);
}
Output:
65524
65524
3276
65524
5
5
5
65524
65524
3276
Explanation:
&i: read as address of i that is 65524
j: read as j, that represents value in j, that is 65524
&j: read as address of j which is 3276
*&j: read as value at address of j that is 65524
i: read as i, that represents value in i that is 5
*(&i): same as *&i: read as value at address of i that is 5
*j: read as value at address contained in j that is 5
Note operand of value at operator (*) must be address of some variable.
Pointer
l Pointer is a variable that contains address of another variable.
l Address of variable is an integer ranges from 0 to 65535.
l Since address range is same as the range of unsigned int variable, we use %u format
specifier when printing address of variable.
l Addresses of variables can be used to access them.
l Variable address can be stored in pointer variable.
l Pointer variable when declared always prefixed with * symbol. This special symbol
tells the compiler that this is a pointer which can only store address of some
variable.
1000
a
1000 1001
2000
k
2000 2001 2002 2003
3000
ch
3000
4000
b
4000 4001 4002 4003 4004 4005 4006 4007
It is important to note that operating system allocates address to every byte. In our
example a is a variable of type int whose address is 1000 (assume), but this is the
address of first byte of int block. 1001 is the address of the next byte. Similarly 2000 is
the address of first byte of float block. Since float block is of 4 bytes, each byte has
different address in a sequential manner.
Address of the first byte of the block of any type is known as base address of that block.
Pointer variable can store one address at a time and it is always base address. To access
any block through pointer requires address of remaining bytes of the block. This is
possible because of two reasons. First, addresses of bytes of a block are always in a
sequence. Second, type of pointer that stores base address.
If the pointer is declared as float pointer (consider s in above example), it is aware of 3
more addresses to be accessed along with base address. Similarly, if the pointer is
declared as double pointer (consider d in above example), it is aware of 7 more
addresses to be accessed along with base address.
Void Pointer
Pointers declared with keyword void are void pointers or generic pointers. Since type of
pointer is void, pointer can not access block, whose address it holds, by just dereferencing pointer. As we studied in the above section, pointers only hold base address
and type of pointer decides how many more bytes need to be accessed. If the type of
pointer is void then we can not know how many more bytes need to be accessed. Every
time when we access block through pointer, typecasting is needful.
i
3
6048
6048
3276
3276
5140
Output is:
6048 6048 6048
3276 3276 5140
333
Pointer jargons
int i; // i is an int
int *j; // j is a pointer to an int
int **k; // k is a pointer to a pointer to an int
Example
main()
{
long int i=3;
int *j;
j = &i;
//Error as incompatible assignment
printf(%d %u, i, &i);
}
Error: cannot convert long* to int*
Example
main()
{
int k, i=3, *j;
j = &i;
k = j; //Error as incompatible assignment
printf(%u, k);
}
Error: cannot convert int* to int
Example
main()
a[0][1]
a[0][2]
a[1][0]
a[1][1]
a[1][2]
1000
1002
1004
1006
1008
1010
p
1000
l Consider the above diagram, let us assume the address of array is 1000 and it is
stored in pointer p.
l p+1 represent address of second array that is 1006. This happens because p is not a
simple pointer to an int, rather it is a pointer to an int array of size 3. Thus every
time when pointer is incremented, it points to next array.
l *(p+1) represent address of first block of first address and if we add 1 to it that is
*(p+1)+1, it means address of next block of the first array.
l Chart below gives you a clear picture of pointer jargons and their meaning.
Expression
P
p+1
*(p+0)
*(p+1)
*(p+0)+1
*(p+0)+2
*(p+1)+0
*(p+1)+1
*(p+1)+2
Meaning
1000
1006
1000
1006
1002
1004
1006
1008
1010
Expression
*(*(p+0)+0)
*(*(p+0)+1)
*(*(p+0)+2)
*(*(p+1)+0)
*(*(p+1)+1)
*(*(p+1)+2)
*p
**p
Meaning
3
5
1
6
7
8
1000
3