Pointers And Arrays |
|
An array is a collection of
similar elements stored in adjacent memory locations. int a[] = { 10, 13, -24,
-35, 67 } ;
float b[] = { 1.2, 3.44,
-5.44, 6.7, 8.9 } ;
long int c[25] ;
If an array is defined and initialized at the same place mentioning its dimension is optional. If similarity and adjacency considerations are met we can build an array of anything, like say, an array of doubles, an array of structures, an array of pointers etc. Size of an array is sum of sizes of individual elements of an array. Base address of an array if address of zeroth element of the array. Mentioning the name of the array
fetches its base address. int a[] = { 10, 13, -24,
-35, 67 } ;
printf ( "%u %u", a,
&a[0] ) ; // both would give base address Array can be passed
to a function element by element. Alternatively we can pass the
entire array to a function at one shot. int a[] = { 10, 13, -24,
int i ;
// passing the array element by element for ( i = 0 ; i < 5 ; i++ ) display ( a[i] ) ; // passing e show ( a, sizeof ( a ) / 2 ) ;
To pass an entire array we simply need to pass its base
address. Whenever we pass an entire array to the function we also
need to pass the size of the array, since the function has no way to
find out how many elements are present in the array.
Array elements can be accessed
using the subscript notation or the pointer notation.
int a[] = { 10, 13, -24,
int i ;
// access using subscript notation for ( i = 0 ; i < 5 ; i++ ) printf ( "%d", a[i] ) ;
// accessing using pointer notation for ( i = 0 ; i < 5 ; i++ ) printf ( "%d", * ( a + i ) ) ; Subscript notation is converted by the compiler into the pointer notation. Hence pointer notation would work faster since using it we would be able to save on the conversion time. All four following expression are
same: a[i * ( a + i ) ( * i + a ) i[a] In the expression a[i]
Out of a and i one must be an integer. The other may
either be an array name or a pointer. An array of pointers is different
than a pointer to an array. int *a[1 int ( *b )[10] ;
a is an array of pointers, whereas, b is
pointer to an array. Incrementing a using a++ is
illegal. On incrementing b it would start pointing to
the next location of its type. What would be the output of
following program main(
)
{
int arr[ ] = { 0, 1, 2, 3, 4 } ;
int *ptr ;
for ( ptr = arr + 4 ; ptr >>= arr ; ptr--
)
printf ( "%d ", arr [ ptr - arr ] ) ;
}
Output Explanation Now things are getting really
complicated, as the printf( ) would justify. Let us begin with
the for loop. Firstly ptr is assigned the address 6012,
the address of the fourth integer from the base address. Since
this address is greater than the base address, the condition is satisfied
and the control reaches printf( ) . What does arr [ ptr - arr
] evaluate to? ptr - arr means 6012 - 6004 , which yields 4,
and hence arr[4] prints out the fourth element of the
array. Then ptr-- reduces ptr to 6010. Since 6010 is
greater than the base address 6004, the condition is satisfied and once
again the control reaches the printf( ) . This time ptr - arr
becomes 6010 - 6004 , i.e. 3. Thus arr[3] prints out 3. This
process is repeated till all the integers in the array have been printed
out. Possibly an easier way of understanding the expression ptr - arr
would be as follows. Suppose ptr contains 6012 and arr contains 6004.
We can then view the subtraction as ( arr + 4 - arr ) , since ptr
is nothing but arr + 4 . Now I suppose its quite logical to
expect the result of the subtraction as 4.
What would be the output of following
program
main {
static int a[ ] = { 0, 1, 2, 3, 4 } ;
static int *p[ ] = { a, a + 1, a + 2, a + 3, a + 4
}
int **ptr = p
printf ( "\n%u %d", a, *a )
printf ( "%u %u %d", p, *p, **p )
printf ( "\n%u %u %d", ptr, *ptr, **ptr ) ; }
Output Explanation
Looking at the figure 2, this would turn out to be 6004
and 0. When you execute the program, the address may turn out to be
something other than 6004, but the value at the address would be surely
0.
Now look at the second printf( ) .
Here p would give the base address of the
array p[ ] , i.e. 9016; *p would give
the value at this address, i.e. 6004; **p would give
the value at the address given by *p , i.e. value at
address 6004, which is 0. Now onto the last printf( ) .
printf ( "\n%u %u %d", ptr, *ptr, **ptr ) ;
Here ptr contains the base address of the
array p[ ] , i.e. 9016; *ptr would
give the value at this address, i.e. 6004; **ptr
would give the value at the address given by *ptr ,
i.e. value at address 6004, which is 0. What would be the output of following
program main( )
{
static
int a[ ] = { 0, 1, 2, 3, 4 } ;
static
int *p[ ] = { a, a + 1, a + 2, a + 3, a + 4 } ;
int
**ptr = p ;
ptr++
;
printf (
"\n%d %d %d", ptr - p, *ptr - a, **ptr ) ;
*ptr++
;
printf (
"\n%d %d %d", ptr - p, *ptr - a, **ptr ) ;
*++ptr
;
printf (
"\n%d %d %d", ptr - p, *ptr - a, **ptr ) ;
++*ptr
;
printf (
"\n%d %d %d", ptr - p, *ptr - a, **ptr ) ;
} Output Explanation Here ptr has been declared as a
pointer to an integer pointer and assigned the base address of the
array p[ ] , which has been declared as an array of
pointers. What happens when ptr++ gets executed?
ptr points to the next integer pointer in the array p[ ] .
In other words, now ptr contains the address
9018. Now let us analyse the meaning of ptr - p , *ptr -
a and **ptr .
ptr - p Since ptr is containing the address
9018, we can as well say that ptr is containing the
address given by p + 1 . Then ptr - p
is reduced to ( p + 1 - p ) , which yields 1.
*ptr - a ;
*ptr **ptr
ptr contains 9018, so *ptr
yields 6006, and hence **ptr becomes *( 6006 ) , which
yields 1. Thus the output of thefirst ;
printf( ) becomes 1 1 1.
Take a deep breath and then begin with the analysis
of *ptr++ . Here * and ++ both are
unary operators. Unary operators have an associativity of right to left,
hence ++ is performed before * . ++
increments ptr such that ptr now
contains 9020. Then *( 9020 ) is performed, which gives the
value at 9020. But since this value is not assigned to any variable, it
just gets ignored. Now with ptr containing 9020, let us once
again analyse the expressions ptr - p , *ptr - a
and **ptr . ptr - p
Since ptr contains 9020, it can be visualised
as ( p + 2 ) . Thus ptr - p would become
( p + 2 - p ) , which gives 2.
*ptr - a
*ptr would give value at address
9020, i.e. 6008, which is nothing but the address given by a +
2 . Thus the expression becomes ( a + 2 - a ) , which
gives 2.
**ptr
*ptr gives the value at address
9020, i.e. 6008, and *( 6008 ) gives the value at 6008, i.e.
2.
I hope your confidence is building and you are ready to
meet head on the expression *++ptr . Here, since
++ precedes ptr , firstly ptr is incremented
such that it contains the address 9022, and then the value at this address
is obtained. Since the value is not collected in any variable, it gets
ignored. Now having cooked enough pointer stew you can easily imagine that
the output of the third printf( ) would be 3 3
3.
Finally, let us understand the expression
++*ptr . Here obviously, the priority goes to the
* . Thus, this expression increments the value given by
*ptr . Since ptr contains 9022,
*ptr gives value at 9022, i.e. 6010. This value is
incremented to 6012.
So p[3] now contains 6012, whereas
value of ptr remains stationary at 9022. Let us now
analyse the expressions ptr - p , *ptr - a
and **ptr .
ptr - p
ptr contains 9022, therefore
ptr can be imagined as ( p + 3 ) .
Thus ( ptr - p ) becomes ( p + 3 - p )
, which yields 3.
*ptr - a
*ptr **ptr
*ptr yields 6012, therefore
**ptr would yield the value at *ptr , or the
value at 6012, which is >4. |
|
Designed and
Managed by |
|