C Programming Pointers
A pointer is a memory variable that stores a memory address. Pointer can have any name that is legal for other variable and it is declared in the same fashion as other variables but it is always by ‘*’ operator.
A pointer is a derived data type in C. it is built from one of the fundamental data type available in C. Always a pointer stores memory address.
Pointers Features
- A pointer saves the memory space.
- Execution time with pointer is faster because data is manipulated with the address i.e. direct access to memory location.
- The memory is accessed efficiently with the pointers.
- The pointer assigns the memory space and it also releases.
- Dynamically memory is allocated.
- Pointers are used with data structures.
- They are useful for representing two-dimensional and multi-dimensional arrays.
Pointer declaration
The declaration of a pointer variable takes the following form:
Data_type * pointer_name;
- The asterisk (*) tells that the variable pointer_name is a pointer variable.
- Pointer_name points to a variable of type data_type.
Example:
int *x;
float *f;
char *y;
In the first statement, ‘x’ is an integer pointer and it tells to the compiler that it holds the address of an integer variable. In the same way, ‘f’ is a float pointer which stores the address of any float variable and ‘y’ is a character pointer that stores the address of any character variable.
The indirection operator (*) is also called the deference operator. When a pointer is dereferenced, the value at the address stored by the pointer is retrieved.
- A normal variable provides direct access to their own values whereas a pointer provides indirect access to the values of the variable whose address it stores.
- The indirection operator (*) is used in two distinct ways with pointers, declaration and reference.
- When a pointer is declared, the star indicates that it is a pointer, not a normal variable.
- When the pointer is dereferenced, the indirection operator indicates that the value at that memory location stored in the pointer is to be accessed rather than the address itself.
- Also, note that * is the same operator that can be used as the multiplication operator. The compiler knows which operator to call, based on the context.
- The ‘&’ is the address operator and it represents the address of the variable. The %u is used with printf() function for printing the address of a variable. The address of any variable is a whole number. The operator ‘&’ immediately preceding the variable returns the address of the variable.
We can declare the pointer variable in 3 forms:
[quote]int *ptr;
int* ptr;
int * ptr;[/quote]
Initialization of pointer variables
The process of accessing the address of a variable to a pointer variable is known as initialization. All uninitialized pointer will have some unknown values that will be interpreted as a memory address.
Once a pointer variable has been declared we can use the assignment operator to initialize the variable.
#include <stdio.h>
int main ( )
{
int i; //variable declaration
int *ptr; //pointer declaration
ptr=&i; //assigning an address to a pointer
}
Note:
[quote]We can combine the initialization with the declaration. That is int *ptr=&i;[/quote]
Accessing a variable through a pointer
Once a pointer has been assigned the address of a variable, the question remains as to how to access the value of the variable using the pointer? This is done by using another operator *, usually, know as the indirection operator or de-reference operator, or object at that location.
#include <stdio.h>
int main ( )
{
int i,n,*ptr;
ptr=&i;
i=25;
n=*ptr;
return 0;
}
The first line declares i, and n as integer variables and ptr as pointer variable which points to an integer value.
The second line assigns the address of i to a pointer variable ptr and the third line assigns the value 25 to i. the fourth line contains the indirection operator *. When the operator * is placed before a pointer variable in an expression, the pointer returns the values of the variable of which the pointer value is the address. In this case *ptr returns the value of the variable I, because ptr is the address of i.
/* simple example with pointer */
int main ( )
{
int a,b;
int *ptr;
a=10;
b=20;
ptr=&a;
*ptr=30;
ptr=&b;
*ptr=40;
printf("%d %d %d",a,b,*ptr);
return 0;
}
Output:
[quote]30 40 40[/quote]
Note:
- Any type of pointer size is same because it stores the address.
- On DOS based compilers pointer size is 2 bytes. This all are unsigned values 0 to 65535. The total address is allocated at runtime is 65536.
- On UNIX based compiler millions of addresses are available, and pointer size is 4 bytes.
All the pointers have the same sizes because they are storing similar values. But there is a necessity to store the address of character in char*, address of integer in int* and float address in float*. The difference is seen when we pointing the variable by using * operator. For example, if we are using char* pointer to hold integer address then when we using * operator than it points first 1 byte only.
Rules for pointer Operation
- Two pointer variables cannot be added.
- A pointer variable can be added or subtracted with an integer value.
- A pointer variable can be subtracted with an integer value.
- Two pointer variables, a pointer variable with an integer value cannot be multiple.
- A pointer variable can be assigned the address of another variable.
- A pointer variable can be pre-fixed or post-fixed with increment or decrement operator.
- We can compare pointers using equality and inequality operator.
- A value cannot be assigned to an arbitrary address (i.e. &x=10; is illegal).
Arithmetic operations with pointers
Arithmetic operation on pointer variables is also possible. Increase, decrease, prefix & postfix operations can be performed with the help of the pointers.
Data type | Initial Address | Operation | Address after operations | Required bytes |
int i=2; | 4046 | ++ / — | 4048 / 4044 | 2 |
char c=’x’; | 4053 | ++ / — | 4054 / 4053 | 1 |
float f=2.2; | 4058 | ++ / — | 4062 / 4054 | 4 |
long l=2 | 4060 | ++ / — | 4064 / 4056 | 4 |
- Addition: a number can be added to a pointer or addition of two variables through pointers is also possible. In the first printf() statement value of ‘b’ is added to pointer of ‘a’ i.e. *p.
- Subtraction: a number can be subtracted from a pointer. Subtraction of two variables through pointers is also possible. In the second printf() statement value of ‘b’ is subtracted from pointer of ‘a’ i.e. *p.
- Multiplication: multiplication of two pointers or a multiplication of number with pointer variable can be done. In the third printf() statement multiplication of variable ‘a’ and ‘b’ is done through their pointers ‘*p’ and ‘*j’.
/*arithmetic operations using pointers. */
#include <stdio.h>
int main()
{
int a=25, b=10, *p, *j;
p=&a;
j=&b;
printf("\n addition a+b=%d",*p+b);
printf("\n substraction a-b=%d",*p-b);
printf("\n product a*b=%d",*p**j);
printf("\n division a/b=%d",*p / *j);
printf("\n a mod b =%d",*p % *j);
return 0;
}
Output:
[quote]Addition a+b = 35
Substraction a-b = 15
Product a*b = 250
Division a/b = 2
A mod b = 5[/quote]
Note: the following things are not possible.
- Addition of two addresses (pointers).
- Multiplication of addresses or multiplication of address with a constant.
- Division of address with a constant.
Pointer as a function argument
Arguments can generally be passed to function in one of the two ways
- Sending the values of the arguments.
- Sending the addresses of the arguments.
In the first method, the ‘value’ of each of the actual arguments in the calling function is copied into corresponding formal arguments of the called function. With this method, the changes made to the formal arguments in the called function have no effect on the values of actual arguments in the called function. The following program illustrates the ‘call by value’ or ‘pass by value’.
That the value of v1 and v2 remain unchanged even after exchanging the value of n1 and n2.
/*call by value example*/
#include <stdio.h>
void swap (int n1, int n2)
{
int t;
t=n1;
n1=n2;
n2=t;
printf ("\nn1=%d n2=%d",n1,n2);
}
int main( )
{
int v1,v2;
v1=10;
v2=20;
swap(v1,v2);
printf("\nv1=%d v2=%d",v1,v2);
return 0;
}
Output:
[quote]n1=20 n1=10
v1=10 v2=20[/quote]
In the second method call by address, the address of actual argument in the calling function are copied into the formal argument of the called function. This means that, using these addresses, we would have an access to the actual arguments and hence we would be able to manipulate them. The following program illustrates the ‘call by address or ‘call by reference’.
/*call by value example*/
#include <stdio.h>
void swap (int *p1, int *p2)
{
int t;
t=*p1;
*p1=*p2;
*p2=t;
}
int main( )
{
int v1,v2;
v1=10;
v2=20;
swap(&v1,&v2);
printf("\nv1=%d v2=%d",v1,v2);
return 0;
}
Output:
[quote]v1=20 v2=10[/quote]
Note:
That this program manages to exchange the values of v1 and v2 using their addresses stored in p1 and p2.
Pointer to function
A function, like a variable, has a type and an address location in the memory. It is therefore, possible to declare a pointer to a function, which can then be used as an argument in another function. A pointer which is pointing to dead location is called dangling pointer.
/* pointer to function example */
int* fun( )
{
int a;
a=25;
return &a;
}
int main ( )
{
int *ptr;
ptr=fun( );
*ptr=35;
printf("%d",*ptr);
return 0;
}
Pointers and Arrays
Array name by itself is an address or pointer. It points to the address of the first element (0th) element of an array. The elements of the array together with their addresses can be displayed by using array name itself. Array elements are always stored in contiguous memory locations.
One dimensional array with a pointer
/* Example on One dimensional */
#include <stdio.h>
int main()
{
int arr[5]={10,20,30,40,50}, p=0;
for (p=0;p<5;p++)
{
printf("value of arr[%d]=”,p);
printf("%d | ",arr[p]);
printf("%d | ",*(arr+p));
printf("%d | ",*(p+arr));
printf("%d | ",p[arr]);
printf("address of arr[%d]=%u\n",p,&arr[p]);
}
return 0;
}
- arr[p]: displays various array elements. Here ‘arr’ refers to the address and ‘p’ refers to element number.
- *(arr+p): arr+p is the addition of a constant with the base address of an array.
- *(p+arr): this is the same as above.
- p[arr]: this is same as arr[p]. here, ‘p’ refers to the element number and ‘arr’ refers to the base address. By varying ‘p’ and ‘arr’ the various elements of the array are displayed.
Two-dimensional arrays with a pointer
/* Example on two dimensional array with pointer */
#include <stdio.h>
int main()
{
int i;
int a[][3]={{1,2,3},{4,5,6},{7,8,9}};
printf("\tElements of an array with their addresses.\n\n");
for (i=0;i<9;i++)
{
printf("%8u",&a[0][0]+i);
printf("[%d]",*(&a[0][0]+i));
if(i==2 || i==5)
printf("\n");
}
return 0;
}
Output:
[quote]
Elements of an array with their addresses.
1[4052] 2[4054] 3[4056]
4[4058] 5[4060] 6[4062]
7[4064] 8[4066] 9[4068]
[/quote]
An array of pointers
it is nothing but a collection of addresses. Here, we store the address of variables for which we have to declare an array as a pointer.
/* Example on array of pointers */
#include <stdio.h>
int main()
{
int *arrp[3];
int arr[3]={5,10,15},k;
for (k=0;k<3;k++)
arrp[k] = arr+k;
printf("\n\tAddress element\n");
for (k=0;k<3;k++)
{
printf("\t%u", arrp[k]);
printf("\t%7d\n",*(arrp[k]));
}
return 0;
}
Output:
[quote]Address element
4060 5
4062 10
4064 15[/quote]
Pointers to pointers
Pointer is known as a variable containing address of another variable. The pointer variables also have an address. The pointer variable containing address of other pointer variables is called a pointer to pointer. This chain can be continued to any extent.
Here, the pointer variable ptr3 contains the address of the pointer variable ptr2 and ptr2 contains the address ptr1 which is pointing to a variable. This is known as multiple indirections.
A variable that is a pointer to a pointer to pointer must be declared using additional indirection operator symbol in front of the name.
/* Example for pointer to pointer concept*/
int main ( )
{
int i;
int *ptr;
int **pptr;
int ***ppptr;
ptr=&i;
pptr=&ptr;
ppptr=&pptr;
i=25;
printf("%d %d %d %d",i,*ptr,**pptr,***ppptr);
return 0;
}
Pointers and strings
pointer usage on strings is similar to arrays only.
/* Example on pointer to string */
int main()
{
char name[15], *ch;
printf(“enter ur name:”);
gets(name);
ch=name;
while(*ch!=’\0’)
{
printf(“%c”,*ch);
ch++;
}
return 0;
}