A pointer is a variable that represents the location of a data item, such as a variable or an array element. 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. Pointers provide a way to return multiple data items from a function via function arguments to
be specified as arguments to a given function.

Pointers are also closely associated with arrays and therefore provide an alternate way to access individual array elements.

Within the computer’s memory, every stored data item occupies one or more adjacent memory cells. The number of memory cells required to store a data item depends on the type of data item. For example, a single character will be stored in 1 byte of memory integer usually requires two adjacent bytes, a floating point number may require four adjacent bytes.

How to declare a Pointer in C?

A pointer is declared just like we declare a variable. There is only one difference in declaration is that we add an asterisk * in front of it to indicate that it’s a variable which is a pointer. For example

you can also declare the pointers as

How Pointer work?

Lets write an example to demonstrate the use of pointers.

Now pnum will be having the address of the number variable.

Initializing pointers

It is often a good practice to initialize the variable while declaring. It is very easy to initialize a pointer to the address of a variable that has already
been defined.

You can also initialize the pointer to the default null value.

Here is a simple example that demonstrates the different aspects of the pointer operations.

The and * Operators

Suppose V is a variable that represents some particular data item. The compiler will automatically assign memory cells for this data item. The data item can be accessed if we know the location of the first memory cell. The address of V?S memory location can be determined by the expression & V, where & is a unary operator, called the address operator, that evaluates the address of its operand.

Now let us assign the address of V to another variable, PV. Thus,

This new variable is called a pointer to V, since it “Points” to the location where V is stored in memory. Remember, however, that PV represents V?s address, not its value. Thus, Pv is called pointer variable.

Relationship between PV and V (where PV = &V and V = *PV)

The data item represented by V can be accessed by the expression *PV where * is a unary operator, that operates only on a pointer variable. Therefore, PV and V both represent the same data item. Furthermore, if we write PV = &V and U = PV, then u and v will both represent the same values i.e., the value of V will indirectly be assigned to u.

Example :

int quantity = 179 ;

The statement instructs the system to find a location for the integer quantity and puts the value 179 in that location. Let us re-assume that the system has chosen the address location 5000 for quantity.

Representation of a Variable

Remember, since a pointer is a variable, its value is also stored in the memory in another location.

The address of P can be assumed to be 5048.

What is Dynamic Memory Allocation?

C programming requires that the number of elements in an array should be specified at compile time. Many languages permit a programmer to specify an array’s size at run time. The process of allocating memory at run time is known as dynamic memory allocation. The library functions used for allocating memory are :

  1. malloc()  – Allocates requested size of bytes and returns a pointer to the first byte of the allocated space
  2. calloc()  – Allocates space for an array of element, initializes them to zero and then returns a pointer to the memory

Memory Allocation Process

Let us first look at the memory allocation process associated with a C program. Fig. below shows the conceptual view of storage of a C program in memory.

  • Local Variable Stack
  • Free Memory Heap
  • Global Variables
  • C Program instructions

The program instructions and global and static variables are stored in a region known as permanent storage area and the local variables are stored in another area called stack. The memory space that is located between these two regions is available for dynamic allocation during execution of the program. The free memory region is called the heap. The size of the heap keeps changing when program is executed due to creation and death of variables that are local to functions and blocks. Therefore, it is possible to encounter memory “overflow” during dynamic allocation process. In such situations, the memory allocations functions mentioned above returns a NULL pointer.

Allocating a block of Memory

A block of memory may be allocated using the function malloc(). The malloc() function reserves a block of memory of specified size and returns a pointer of type void. This means that we can assign it to any type of pointer. It takes the following form;

ptr = ( Cast type * ) malloc ( byte size ) ;

Ptr is a pointer of type cast type. The malloc returns a pointer (of cast type) to an area of memory with size byte – size.

Example :
x = ( int * ) malloc ( 100 * size of ( int )) ;

On successful execution of this statement, a memory space equivalent to “100 times the size of an int” bytes is reserved and the address of the first byte of the memory allocated is assigned to the pointer X of type int.

Similarly, the statement
cptr = ( char * ) malloc ( 10 ) ;

allocates 10 bytes of space for the pointer cptr of type char.

Remember, the malloc() allocates a block of adjacent bytes. The allocation can fail if the space in the heap is not sufficient to satisfy the request. If it foils, it returns a NULL. We should therefore check whether the allocation is successful before using the memory pointer.

C Program to Allocate Memory

Write a program that uses a list of integers whose size will be specified interactively at run time.

Output of the program

Allocating Multiple Blocks of Memory

The calloc() function is another memory allocation function that is normally used for requesting memory space at run time for storing derived data types such as arrays and structures. While malloc() allocates a single block of storage space, calloc() allocates multiple blocks of storage, each of the same size, and then allocates all bytes to O. The general form of calloc() function is:

Pointer = (cast type * ) calloc ( n, elem-size );

The above statement allocates contiguous space for n blocks, each of size elem-size bytes. All bytes are initialized to zero and a pointer to the first byte of the allocated region is returned. If there is not enough space, a NULL pointer is returned.

Pointer vs. Arrays

When an array is declared, the compiler allocates a base address and sufficient amount of storage to contain all the elements of the array in contiguous memory locations. The base address is the location of the first element (index 0) of the array. The compiler also defines the array name as a constant pointer to the first element suppose we declare an array X as follows:

Static int X [ 6 ] = { 1, 2, 3, 4, 5, 6 } ;

Suppose the base address of X is 1000 and assuming that each integer requires two bytes, the five elements will be stored as follows:

ELEMENTS x[0] x[1] x[2] x[3] x[4] x[5]

VALUE 1 2 3 4 5 6

Address 1000 1002 1004 1006 1008 1010

BASE ADDRESS

The name X is defined as a constant pointer pointing to the first clement, x [0] and therefore the value of X is 1000, the location whose X[0] is stored.

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 more from one element to another. The relationship between P and X is shown below:

The address of an element is calculated using its index and the scale factor of the data type. For instance,

address of X[3] = base address + (3 X Scale factor of int) = 1000 + (3 x 2) = 1006

When handling array, instead of using array indexing, we can use pointers to access array elements. Note that X(P+3) gives the value of X[3]. The pointer accessing method is more faster than array indexing.

Pointers and Functions

When an array is passed to a function as an argument, only the address of the first element of the array is passed, but not the actual values of the array elements. 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 addresses to a function, the parameters receiving the addresses should be pointers. The process of calling function using pointers to pass the address of variable is known as call by reference. The function which is called by reference can change the value of the variable used in the call.

Program to demonstrate call by reference

When the function change() is called, the address of the variable X is passed into the function change (). Inside change(), the variable P is declared as a pointer and therefore P is the address of the variable X. The following statement  *P = *P + 10; means add 10 to the value stored at address P. Since P represents the address of X, the value of X is changed from 40. Therefore, the output of the program will be 50 not 40.

These, call by reference provides a mechanism by which the function can change the stored values in the calling function.