Pointers
Pointers
Pointers
POINTERS
Pointers:
Understanding a pointer
A pointer is a variable that contains an address which is a location of another variable in memory.
Since a pointer is a variable, its value is also stored in the memory in another location.
Suppose we assign the address of quantity to a variable p.
The link between the variables p and quantity can be visualized as shown in the figure.
The address of p is 5048. Since the value of variable p is the address of the variable quantity, we
may access the value of a quantity by using the value of p and therefore, the variable p points to
the variable quantity. Thus, p gets the name ‘pointer’.
{
char a;
int x;
float p,q;
a=’A’;
x=125;
p=10.25,q=18.76;
printf(“%c is stored at address %u. \n”,a,&a);
printf(“%d is stored at address %u. \n”,x,&x);
printf(“%f is stored at address %u. \n”,p,&p);
printf(“%f is stored at address %u. \n”,q,&q);
}
Output:
A is stored at address 4436
125 is stored at address 4434
10.25 is stored at address 4442
18.76 is stored at address 4438
Syntax:
data_type *pt_name
The (*) asterisk tells that the variable pt_name is a pointer variable.
Pt_name needs memory location
Pt_name points to a variable of type data_type
Example:
Method1:
Method2:
int x; //declare a data variable
int *px=&x; //assign the address of data variable to pointer variable
Method3:
int x,*px=&x; //declare data variable and assign address
float a,b;
int x, *p;
p=&a; //wrong
b=*p;
The above declarations will result in erroneous output because we are attempting to assign the address of
float variable to an integer pointer.
Pointers are flexible : we can make the pointer point to different data variables in different
statements
Example:
int x,y,z,*p;
X Y Z
p=&x;
p=&y;
p=&z;
p
Different pointers can be used to point to the same variable.
Example:
int x;
int *p1=&x; p1 p2 p3
int *p2=&x;
int *p3=&x;
As a part of declaration of the pointer variable, we use *. This symbol can also be used as an operator, called as
dereferencing operator or indirection operator. The notation *p means the object that p points to or the
location whose address is stored in p. This operator allows us to access and change the value stored at that
location.
address of a value of a
p a int a= 15;
92 15
int *p;
address 98 address 92
p= &a;
Consider the following set of assignments:
Chain of Pointers
It is possible to make a pointer to point to another pointer, thus creating a chain of pointers as shown.
p2 p1 variable
Here pointer variable p2 contains the address of the pointer variable p1, which points to the location
that contains the desired value. This is known as multiple indirections.
A variable that is a pointer to a pointer must be declared using additional indirection operator symbol in
front of the name
Example:
int **p2;
Example Program:
Output:
Pointer Expressions:
Example:
p1+4
p2-2
p1-p2
If p1 and p2 are both pointers to the same array then p2-p1 gives the number of elements between p1
and p2.
We may also use short hand operators with pointers
p1++;
-p2;
sum+=*p2;
p1>p2
p1==p2
p1!=p2
Example Program:
main()
{
int a,b,*p1,*p2,x,y,z;
a=12;
b=4;
p1=&a;
p2=&b;
x=*p1 * *p2 - 6;
y=4* -*p2/*p1 +10;
printf(“Address of a =%u\n”,p1);
printf(“Address of b=%u\n”,p2);
printf(“\n”);
printf(“a =%d, b=%d\n”,a,b);
printf(“x=%d, y=%d \n”,x,y);
*p2=*p2 +3;
*p1=*p2 -5;
z=*p1 * *p2 -6;
printf(“a =%d, b=%d\n”,a,b);
printf(“z=%d\n”,z);
}
Output:
Address of a=4020
Address of b=4016
a=12,b=4
x=42,y=9
a=2,b=7,z=8
int x[5]={1,2,3,4,5};
Suppose the base address of x is 1000 and assuming that each integer requires two bytes, the five
elements will be stored as follows:
x[0] x[1] x[2] x[3] x[4]
Elements
Value 1 2 3 4 5
Base Address
The name x is defined as a constant pointer to the first element, x[0] and therefore the value of x is
1000, the location where x[0] is stored, that is
X= &x[0]=1000
If we declare p as an integer pointer, then we can make the pointer p to point to the array x by the
following assignment:
p=x;
This is equivalent to
p=&x[0];
Now we can access every value of x using p++ to move from one element to another. The relationship
between p and x is as shown :
p=&x[0](=1000)
p+1=&x[1](=1002)
p+2=&x[2](=1004)
p+3=&x[3](=1006)
p+4=&x[4](=1008)
Address of an element is calculated using its index and the scale factor of the data type:
Example Program:
Program to find the sum of all the elements in an array using pointers
Output:
We know that the name of the array is a constant pointer that points to the 0th element of the array.
In the case of a 2-D array, 0th element is a 1-D array.
So the name of the array in case of a 2-D array represents a pointer to the 0th 1-D array. Therefore in
this case arr is a pointer to an array of 4 elements.
If the address of the 0th 1-D is 2000, then according to pointer arithmetic (arr + 1) will represent the
address 2016, similarly (arr + 2) will represent the address 2032.
Since *(arr + i) points to the base address of every ith 1-D array and it is of base type pointer to int, by
using pointer arithmetic we should we able to access elements of ith 1-D array.
*(arr + i) points to the address of the 0th element of the 1-D array. So,
*(arr + i) + 1 points to the address of the 1st element of the 1-D array
*(arr + i) + 2 points to the address of the 2nd element of the 1-D array
Hence we can conclude that:
*(arr + i) + j points to the base address of jth element of ith 1-D array
Example Program:
Program using pointers to determine the length of a character string
main()
{
char *name;
int length;
char *cptr=”name”;
name=”delhi”;
printf(“%s\n”,name);
while (*cptr!=’\0’)
{
printf(“%c is stored at address %u\n”,*cptr,cptr);
cptr++;
}
length=cptr-name;
printf(“\n Length of the string =%d\n”,length);
}
Output:
DELHI
D is stored at address 54
E is stored at address 55
L is stored at address 56
H is stored at address 57
I is stored at address 58
Array of pointers:
Just like we can declare an array of int, float or char etc, we can also declare an array of pointers, here is
the syntax to do the same.
Example:
int *arrop[5];
Here arrop is an array of 5 integer pointers. It means that this array can hold the address of 5 integer
variables. In other words, you can assign 5 pointer variables of type pointer to int to the elements of this
array.
Example Program:
Output
When an array is passed as an argument to functions, only the address of the first element of the array
is passed.
The function uses this address for manipulating the array elements.
Similarly we can pass the address of a variable as an argument to a function in the normal fashion. When
we pass the address of a variable as an argument the receiving parameter should be pointers. This
process of calling a function using pointers to pass the addresses of variables is known as “Call by
reference”.
Example Program:
Program to exchange the values stored in the two memory location using pointers and functions.
Output:
Some examples:
int *func(int, int); // this function returns a pointer to int
double *func(int, int); // this function returns a pointer to double
Example Program:
Output:
We have already learned that a pointer is a variable which points to the address of another variable of
any data type like int, char, float etc.
Similarly, we can have a pointer to structures, where a pointer variable can point to the address of a
structure variable.
Here is how we can declare a pointer to a structure variable.
struct dog
{
char name[10];
char breed[10];
int age;
char color[10];
};
This declares a pointer ptr_dog that can store the address of the variable of type struct dog. We can now assign
the address of variable spike to ptr_dog using & operator.
ptr_dog = &spike;
At this point ptr_dog points to the structure variable spike, so by dereferencing it we will get the
contents of the spike. This means spike and *ptr_dog are functionally equivalent. For example:
(*ptr_dog).name – refers to the name of dog
(*ptr_dog).breed – refers to the breed of dog
and so on.
Parentheses around *ptr_dog are necessary because the precedence of dot(.) operator is greater than
that of indirection (*) operator.
To access members using arrow (->) operator write pointer variable followed by -> operator, followed by
name of the member.
ptr_dog->name - refers to the name of dog
ptr_dog->breed - refers to the breed of dog
and so on
Example Program:
Output:
Preprocessors
The preprocessor is a program that processes the source program before it is passed onto the compiler
One of the most important features of C language is to offer preprocessor directives. The preprocessor
directives are always initiated at the beginning and it starts with the symbol hash(#). It can be placed
anywhere but quite often it is declared before the main( ) function.
substitute_string part is optional but, are used almost every time in program.
Example of #define
#define PI 3.14
#include <stdio.h>
#define PI 3.1415
void main()
{
int radius;
float area;
printf("Enter the radius: ");
scanf("%d", &radius);
area=PI*radius*radius;
printf("Area=%.2f",area);
}
Output
Enter the radius: 3
Area=28.27
In the above program PI replaces 3.14 during the program execution. In the program instead of writing
the value of PI as 3.14 we define directly the value of PI as 3.14.
Examples:
Macro can also include more than a simple constant value. It can include expressions as well.
#define AREA 5*12.46
#define SIZE sizeof(int)*4
#define D 45-22
Syntax:
#define identifier(f1,f2,….fn) string
Examples:
Nesting of Macros:
We can use one macro in the definition of another macro. That is macro definitions may be nested.
Examples:
#define M 5
#define N M+1
#define SQUARE(x) ((x)*(x))
#define CUBE(x) (SQUARE(x)*(x))
#include <stdio.h>
Here, "stdio.h" is a header file and the preprocessor replace the above line with the contents of header
file.
Example:
#include<stdio.h>
#include<conio.h>
void main()
{
clrscr();
printf(“India is my country”);
}
O/P
India is my country
#ifdef <identifier>
{
statement 1;
statement 2;
}
#else
{
statement 1;
statement 2;
}
#endif
Example 1:
#include<stdio.h>
#include<conio.h>
#define LINE 1
void main()
{
clrscr();
#ifdef LINE
printf(“This is line number one”);
#else
printf(“This is line number two”);
#endif
getch();
}
O/P
This is line number one
Example 2:
#include<stdio.h>
#include<conio.h>
#define E =
void main()
{
int a,b,c,d;
clrscr();
#ifdef E
{
a E 2;
b E 3;
printf(“A=%d, B=%d”, a,b);
}
#else
{
c=2;
d=3;
printf(“C=%d & D=%d”, c,d);
}
#endif
getch();
}
O/P
A=2 , B=3
The #ifndef works exactly opposite to that of #ifdef preprocessor tests whether the identifier has
defined substitute text or not.
If identifier is defined then #else block is complied and executed and the compiler ignores #if block even
if errors are intentionally made.
Error message will not be displayed.
Syntax:
#ifndef<indeftifier>
{
statement 1;
statement 2;
}
#else
{
statement 1;
statement 2;
}
#endif
Example:
#include<stdio.h>
#include<conio.h>
#define T 8
void main()
{
clrscr( );
#ifndef T
printf(“\n Macro is not defined”);
#else
printf(“\n Macro is defined”);
#endif
}
O/P
macro is defined
The #error directive is used to display user defined message during compilation of the program.
Example:
#include<stdio.h>
#include<conio.h>
#define B 1
void main()
{
clrscr();
#if!defined(A)
#error MACRO A IS NOT DEFINED
#else
printf(“Macro found”);
#endif
}
Causes the complier to imagine the line number of the next source line as given by <constant> and , <identifier>
gives the current input file. If identifier is absent, then the current file name remains unchanged.
Example:
#line 15 pragma.c