Lecture 13
The most crucial of all of C’s grammars is
pointers. Many other programming languages have the similar concept as pointer
in C, but they merely do not use the best of pointers. C uses pointers as its
inevitable part. Though the understanding of pointers is the most difficult
part in learning C, once you have the clean idea on pointers, you will see that
by using pointers, you can solve any problem in C.
Consider the declaration-
int i = 3;
This declaration tells the C compiler to:
(a) Reserve space in memory to hold the integer
value.
(b) Associate the name i with this
memory location.
(c) Store the value 3 at this location.
We see that the computer has selected memory
location 65524 as the place to store the value 3. The location number 65524 is
not a number to be relied upon, because some other time the computer may choose
a different location for storing the value 3. The important point is, i’s
address in memory is a number.
We can print this address number through the
following program:
The output of the above program would be:
Look at the first printf( ) statement
carefully. ‘&’ used in this statement is C’s ‘address of’ operator. The
expression &i returns the address of the variable i, which in
this case happens to be 65524. Since 65524 represents an address, there is no
question of a sign being associated with it. Hence it is printed out using %u,
which is a format specifier for printing an unsigned integer. We have been
using the ‘&’ operator all the time in the scanf( ) statement.
The other pointer operator available in C is ‘*’,
called ‘value at address’ operator. It gives the value stored at a particular
address. The ‘value at address’ operator is also called ‘indirection’ operator.
Observe carefully the output of the following
program:
The expression &i gives the address
of the variable i. This address can be collected in a variable, by
saying,
j = &i ;
But remember that j is not an ordinary
variable like any other integer variable. It is a variable that contains the
address of other variable (i in this case). Since j is a variable
the compiler must provide it space in the memory. Once again, the following
memory map would illustrate the contents of i and j.
As you can see, i’s value is 3 and j’s
value is i’s address.
But wait, we can’t use j in a program
without declaring it. And since j is a variable that contains the
address of i, it is declared as,
int *j ;
This 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. How do we justify the usage of * in the declaration,
int *j ;
Let us go by the meaning of *. It stands
for ‘value at address’. Thus, int *j would mean, the value at the address
contained in j is an int.
Here is a program that demonstrates the
relationships we have been discussing.
The output of the above program would be:
Look at the following declarations,
int *alpha ;
char *ch ;
float *s ;
Here, alpha, ch and s are
declared as pointer variables, i.e. variables capable of holding addresses.
Remember that, addresses (location nos.) are always going to be whole numbers,
therefore pointers always contain whole numbers. Now we can put these two facts
together and say—pointers are variables that contain addresses, and since
addresses are always whole numbers, pointers would always contain whole
numbers.
The declaration float *s does not mean
that s is going to contain a floating-point value. What it means is, s
is going to contain the address of a floating-point value. Similarly, char
*ch means that ch is going to contain the address of a char value.
Or in other words, the value at address stored in ch is going to be a char.
The concept of pointers can be further extended.
Pointer, we know is a variable that contains address of another variable. Now
this variable itself might be another pointer. Thus, we now have a pointer that
contains another pointer’s address. The following example should make this
point clear.
The output of the above program would be:
Remember that when you run this program the
addresses that get printed might turn out to be something different than the
ones shown in the figure. However, with these addresses too the relationship
between i, j and k can be easily established.
Observe how the variables j and k have
been declared,
int i, *j, **k ;
Here, i is an ordinary int, j is
a pointer to an int (often called an integer pointer), whereas k is
a pointer to an integer pointer. We can extend the above program still further
by creating a pointer to a pointer to an integer pointer. In principle, you
would agree that likewise there could exist a pointer to a pointer to a pointer
to a pointer to a pointer. There is no limit on how far can we go on extending
this definition. Possibly, till the point we can comprehend it. And that point
of comprehension is usually a pointer to a pointer. Beyond this one rarely
requires to extend the definition of a pointer. But just in case...
The following program illustrates
another way to use pointers, this time with characters,
#include <stdio.h>
main(){
char c = 'Q';
char *char_pointer = &c;
printf("%c %c\n", c, *char_pointer);
c = 'Z';
printf("%c %c\n", c, *char_pointer);
*char_pointer = 'Y';
printf("%c %c\n", c, *char_pointer);
}
Guess what will be the output…
1 comments:
Awesome blog. chemical wash aircon price
Post a Comment