Pointers in C Language

Pointers in C Language

What are Pointers? :

A pointer is a variable whose value is the address of another variable i.e., direct address of the memory location. Like any variable or constant, you must declare a pointer before you can use it to store any variable address. Pointers are used frequently in C, as they have a number of useful applications. For example, pointers can be used to pass information back and forth between a function and its reference point. The pointers in 'C' language increase the efficiency of program to a large extent. Although they are difficult to use but it is a very powerful tool while managing the memory.

The actual data type of the value of all pointers, whether integer, float, character, or otherwise, is the same, a long hexadecimal number that represents a memory address. The only difference between pointers of different data types is the data type of the variable or constant that the pointer points to. The unary or monadic operator ‘&’ gives the “address of a variable”. The indirection or dereference operator ‘*’ gives the “contents of an object pointed to by a pointer”.

Pointers are used for many reasons like:

•    Pointers reduce the length and complex city of program.
•    They increase the processing speed.
•    They save the memory to a very large extent.
•    A pointer enables to access any variable whether it may be outside the function i.e. a direct control over a variable can be made using pointers.

Pointer syntax:

Pointer variables, like all other variables, must be declared before; they may be used in C program. When a pointer variable is declared, the variable name must be preceded by an asterisk (*). This identifies the fact that the variable is a pointer. The data type that appears in the declaration refers to the object of the pointer. i.e. the data item that is stored in the address represented by the pointer, rather than the pointer itself. Thus a pointer declaration may be written in general terms as:

Data-type *ptr;
Where ptr is the name of the pointer variable, and data-type refers to the data type of the pointer object.

For example, a C program contains the following declarations.

int i,*ptri;
float f,*ptrf;

The first line declares ‘i’ to be an integer type variable and ptri to be a pointer variable whose object is an integer quantity. The second line declares f to be a floating-point type variable and ptrf to be a pointer variable whose object is a floating point quantity.
Within a variable declaration, a pointer variable can be initialized by assigning in the address of another variable, remember that the variable whose address is assigned to the pointer variable must have been declared earlier in the program, for example,
int i;
int *ptri=&i;
The first line declares i to be integer type variable and the second line declares ptri to be a pointer variable whose object is an integer point quantity. In addition, the address of i is initially assigned to ptri.

How to Use a Pointer?
A pointer can be used in two contexts.

•    For accessing the address of the variable whose memory address the pointer stores. consider the following code:
 char ch = 'c';
char *chptr = &ch;
Now, whenever we refer the name ‘chptr’ in the code after the above two lines, then compiler would try to fetch the value contained by this pointer variable, which is the address of the variable (ch) to which the pointer points. i.e. the value given by ‘chptr’ would be equal to ‘&ch’.

For example:

char *ptr = chptr;

The value held by ‘chptr’ (which in this case is the address of the variable ‘ch’) is assigned to the new pointer ‘ptr’.
•    For accessing the value of the variable whose memory address the pointer stores. Continuing with the piece of code used above :
char ch = 'c';
char t;
char *chptr = &ch;
t = *chptr;
We see that in the last line above, we have used ‘*’ before the name of the pointer. This operator when applied to a pointer variable name (like in the last line above) yields the value of the variable to which this pointer points. Which means, in this case ‘*chptr’ would yield the value kept at address held by chptr. When used with pointers, the asterisk ‘*’ operator is also known as ‘value of’ operator.

NULL Pointers in C:

It is always a good practice to assign a NULL value to a pointer variable in case you do not have exact address to be assigned. This is done at the time of variable declaration. A pointer that is assigned NULL is called a null pointer.
The NULL pointer is a constant with a value of zero defined in several standard libraries. Consider the following program:

#include <stdio.h>
int main ()
   int *ptr = NULL;
   printf ("The value of ptr is : %x \n", ptr );
   return 0;
When the above code is compiled and executed, it produces following result:
The value of ptr is 0
On most of the operating systems, programs are not permitted to access memory at address 0 because that memory is reserved by the operating system. However, the memory address 0 has special significance; it signals that the pointer is not intended to point to an accessible memory location. But by convention, if a pointer contains the null (zero) value, it is assumed to point to nothing.

Concepts of pointers:

Pointers have many but easy concepts and they are very important to C programming. There are following few important pointer concepts:

•    C - Pointer arithmetic: There are four arithmetic operators that can be used on pointers: ++, --, +, -
•    C - Array of pointers: You can define arrays to hold a number of pointers.
•    C - Pointer to pointer: Allows you to have pointer on a pointer and so on.
•    Passing pointers to functions in C: Passing an argument by reference or by address both enable the passed argument to be changed in the calling function by the called function.
•    Return pointer from functions in C: C allows a function to return a pointer to local variable, static variable and dynamically allocated memory as well.

C - Pointer arithmetic:

C pointer is an address which is a numeric value. Therefore, you can perform arithmetic operations on a pointer just as you can a numeric value. There are four arithmetic operators that can be used on pointers: ++, --, +, and -.
To understand pointer arithmetic, let us consider that ptr is an integer pointer which points to the address 1000. Assuming 32-bit integers, let us perform the following arithmetic operation on the pointer:
Now after the above operation, the ptr will point to the location 1004 because each time ptr is incremented, it will point to the next integer location which is 4 bytes next to the current location. This operation will move the pointer to next memory location without impacting actual value at the memory location. If ptr points to a character whose address is 1000, then above operation will point to the location 1001 because next character will be available at 1001.

•    Incrementing a Pointer: A pointer variable is incremented by using an increment operator then its address value is not increased by 1 but it will be increased by a complete address this type of incrementation is called pointer incrementation and the length which pointer is incrementing is called scalar factor.
•    Decrementing a Pointer: The same considerations apply to decrementing a pointer, which decreases its value by the number of bytes of its data type.
•    Pointer Comparisons: Pointers may be compared by using relational operators, such as ==, <, and >. If p1 and p2 point to variables that are related to each other, such as elements of the same array, then p1 and p2 can be meaningfully compared.


#include< stdio.h >
main ()
int ptr1,ptr2;
int a,b,x,y,z;
a=30; b=6;
x=*ptr1+ *ptr2 6;
y=6*- *ptr1/ *ptr2 +30;
printf ("\n Address of a +%u",ptr1);
printf ("\n Address of b %u",ptr2);
printf ("\n a=%d, b=%d", a,b);
printf("\n x=%d ,y=%d", x,y);
ptr1=ptr1 + 70;
ptr2= ptr2;
printf ("\n a=%d, b=%d," a, b);

C - Array of pointers:

Array is a collection of multiple data items which are represented by using a single identifier. Since a single identifier representing all the data items will have generally a continuous allocation in arrays there is one base address to which all the contiguous memory location are attached. These memory locations are having then difference in addresses and their addresses are continuous in manner.

Since the array is having a base address and all the memory location is continuous in manner and they store the data item of some type and the scalar factor can be used in the pointers. Hence if a pointer variable is made pointing to the base address of the any array then all successive element of that array can be access by incrementing the pointer variable till the end of the array.in general terms,a two-dimensional array can be defined as a one-dimentional array of pointers by:
data-type *array [expression 1]                   


int main()
int a [10], *p;
P=&a [0]; [0]
P=& a [10] [10]
This will assign the base address of array 'a' in the pointer variable p. Now if the value of the second index has to be accessed then the pointer p is incremented and now it is pointing to the next index to the base address. This can be done by using increment operator like p++.

C - Pointer to pointer:

A pointer to a pointer is a form of multiple indirections, or a chain of pointers. Normally, a pointer contains the address of a variable. When we define a pointer to a pointer, the first pointer contains the address of the second pointer, which points to the location that contains the actual value.

A variable that is a pointer to a pointer must be declared as such. This is done by placing an additional asterisk in front of its name. For example, following is the declaration to declare a pointer to a pointer of type int:

int **var;
When a target value is indirectly pointed to by a pointer to a pointer, accessing that value requires that the asterisk operator be applied twice.

Passing pointers to functions in C:

pointers are often passed to a function as arguments. This allows the data items within calling portion of the program to be accessed by the function, altered within the function, and returned to the calling portion of the program in altered form.
When an argument is passed by value, the data item is copied to the function. Thus, an alteration made to the data item within the function is not carried over into calling routine. When an argument is passed by reference, however (i.e. when a pointer is passed to a function), the address of a data item is passed to the function. The contents of that address can be accessed freely, either within the function or within the calling routine. Moreover, any change that is made to the data item will be recognized in both the function and the calling routine. Thus, the use of a pointer as a function argument permits the corresponding data item to be altered globally from within the function.
When pointers are used as arguments to a function, some care is required with the formal argument declarations within the function. Specifically, formal pointer arguments that must each be preceded by an asterisk. Function prototypes are written in the same manner. If a function declaration does not include variable names, the data type of each pointer argument must be followed by an asterisk.

A function pointer can be declared as:
<return type of function> (*<name of pointer>) (type of function arguments)

For example:

int (*fptr)(int, int)
The above line declares a function pointer ‘fptr’ that can point to a function whose return type is ‘int’ and takes two integers as arguments.
int func (int a, int b)
    Printf ("\n a = %d\n",a);
    printf ("\n b = %d\n",b);
    return 0;

int main(void)
    int (*fptr)(int,int); // Function pointer

    fptr = func; // Assign address to function pointer
    func (2,3);
    fptr (2,3);
    return 0;

In the above example, we defined a function ‘func’ that takes two integers as inputs and returns an integer. In the main () function, we declare a function pointer ‘fptr’ and then assign value to it. Note that, name of the function can be treated as starting address of the function so we can assign the address of function to function pointer using function’s name.
Dynamic memory allocation:
Dynamic memory allocation is the practice of assigning memory locations to variables during execution of the program by explicit request of the programmer. Dynamic allocation is a unique feature to C (amongst high level languages). It enables us to create data types and structures of any size and length to suit our programs need within the program.
Finally, the dynamically allocated memory area, the area is secured in a location different from the usual definition of a variable. There is also the name depending on the role of memory space and just go. Used in the dynamic memory allocation area is called the heap. In contrast, the variables are usually allocated to the location of the stack. Variables are allocated on the heap, even if it was secured out of the scope, continues to exist. For example, in function, if you create a dynamic variable, but missing out the function and will continue to exist on the heap.
The functions malloc (), realloc (), calloc () and free (), the Library functions stdlib.h, malloc.h or are responsible for this task. All data are stored in the free store (heap), which is limited to 64k a stack in the beginning, this varies from machine. All variables were declared so far on the stack, now you tell me where to go, in an indirect way.
The following functions are used in c for purpose of memory management.
malloc ()
calloc ()
realloc ()
free ()

malloc(): The malloc()  function dynamically allocates memory when required. This function allocates ‘size’ byte of memory and returns a pointer to the first byte or NULL if there is some kind of error. Format is as follows.
void * malloc (size_t size);
Specifies in bytes the size of the area you want to reserve the argument. It returns the address as the return value of the dynamically allocated area. In addition, returns NULL if it fails to secure the area. The failure to ensure that the situation is usually that is out of memory. The return type is of type void *, also receive the address of any type. The fact is used as follows.
double * p = (double *) malloc (sizeof (double));
calloc(): The calloc function is used to allocate storage to a variable while the program is running. This library function is invoked by writing calloc (num,size).This function takes two arguments that specify the number of elements to be reserved, and the size of each element in bytes and it allocates memory block equivalent to num * size . The function returns a pointer to the beginning of the allocated storage area in memory. The important difference between malloc and calloc function is that calloc initializes all bytes in the allocation block to zero and the allocated memory may/may not be contiguous. Calloc function is used to reserve space for dynamic arrays. Has the following form.
void * calloc (size_t n, size_t size);
Number of elements in the first argument specifies the size in bytes of one element to the second argument. A successful partitioning, that address is returned, NULL is returned on failure.
For example, an int array of 10 elements can be allocated as follows.
int * array = (int *) calloc (10, sizeof (int));
realloc(): With the function realloc, you can change the size of the allocated area once. Has the following form.
void * realloc (void * ptr, size_t size);
The first argument specifies the address of an area that is currently allocated to the size in bytes of the modified second argument. Change the size, the return value is returned in re-allocated address space. Otherwise it returns NULL.
The address of the source address changed, but the same could possibly be different, even if the different areas of the old style, because it is automatically released in the function realloc, for the older areas it is not necessary to call the free function. However, if the function fails and returns NULL, realloc, the older area is to remain still valid. Therefore, the first pointer argument of the function realloc, both can be NULL pointer return value is not returned.


Post a Comment