Introduction

  • when we declare a variable of any datatype in our program, we refer to that location in memory by certain name but at the machine level, that location has a memory address, which are used by the os during the processing.

Definition

  • A pointer is a variable that points to another variable by holding its address i.e. it holds the memory address of different types of variables such as simple variable, array, string, pointer itself etc.
  • Simply a variable that contains an address, which is actually has location of another variables in memory.

Characteristics Feature

  • Helps in Dynamic memory is allocation.
  • Because a pointer holds an address rather than a value, it has two parts – There is the pointer and the value pointed to.The pointer itself holds the address and that address, points to a value.
  • To determine the address of a variable without using pointer, “&” called address  operator is available/used in C for this purpose. The operator & and the immediately preceding variable name returns the address of that variable associated with it. The & operator can be used only with simple variables or array elements. It cannot be applied to expressions, constants, or register variables.
  • C has other unary pointer operator “*” called as indirection operator. It returns a value stored at that address when used in the program but denotes as a pointer variable when used in declaration section.
  • The format specifier %u is used to get the address of variables with the help of pointer.

Advantages

  • The program execution time becomes faster using pointer as the data is manipulated with the help of addresses directly.
  • Saves the memory space.
  • The memory access time is very efficient/fast.
  • Pointers are useful, powerful, and relatively trouble-free tools especially for a data structure work and design and analysis of algorithms.

Disadvantages

  • Pointers help in direct manipulation of memory addresses hence many times pointers are the main cause of run time errors because of improper use of memory.
  • The pointer does not hold a value in the traditional sense.

    Pointer Declaration & Assignments

    • In C, every variable must be declared for its data type before it is used. We declare the data type of the pointer variable as that of the type of the data that will be stored at the address to which it is pointing to. In C, we define a pointer variable by preceding its name with an asterisk(*) symbol. The “*” informs the compiler that we want a pointer variable, i.e. to set aside the bytes that are required to store the address in memory. The int/float says that we intend to use our pointer variable to store the address of an integer/float variables.
    int num1, num2 ;
    int *ptr1, *ptr2 ;      //Pointer variables declaration to store the address of integer.
    float qty1, qty2 ;
    float *ptr3, *ptr4 ;    //Pointer variables declaration to store the address of float.
    Here ptr1, ptr2, ptr3, ptr4 are called pointer variables.
    • It is suggested that make sure to initialize all pointers to a valid address in the program before dereferencing/use them.
    • The uninitialized pointer points to a random location in memory when we declare it. It could be pointing into the system stack, or the global variables, or into the program’s code space, or into the operating system.Almost always, an uninitialized pointer or a bad pointer address causes the fault in the program.
    • Within a variable declaration, a pointer variable can be initialized by assigning it the address of another variable. The variable whose address is assigned to the pointer variable must be declared earlier in the program.

    int *ptr;
    int x;
    ptr = &x;
    *ptr=100;  //Assigning/initialization of x variable using pointer.

    • To assign the address of variables –
    ptr1=&num1;
    ptr2=&num2;
    ptr3=&qty1;
    ptr4=&qty2;

    Pointer to Pointer

    • when a pointer stores the address of another pointer, it is called pointer to pointer.
    • Pointer to pointer is declared as multistar symbol with variable name as below –
    int num = 50;
    int *ptr1;
    int **ptr2;
    int ***ptr3;
    ptr1 = #
    ptr2 = &ptr1;
    ptr3=&ptr2;
    Here **ptr2, ***ptr3 are pointer to pointer. Here higher star pointer stores the address of just less star pointer and so on.

    Pointer Operators

    • Pointer supports several type of operators (such as arithmetic operators, relational operators etc.) in their operations as normal variable does but with certain conditions which are described in pointer arithmetic.

    Pointer Arithmetic

    • Like normal variables, pointer variables can also be used in arithmetic expressions.
    • The following operations can be performed on pointers : –
      • Pointers can be incremented or decremented to point to different memory locations. For examples –
    ptr=ptr+1;
    ptr1=ptr1-1;
    ptr3 = ptr2 + 5;
      • If two/more pointers are properly declared and initialized then the following operations can be performed :-
    int num=0;
    num= num+ *ptr1;
    num= num- *ptr1;
    *ptr1 = *ptr2 + 7;
    num= *ptr1 + *ptr2;
    num= *ptr1 – *ptr2;
    num= *ptr1 * *ptr2;
    num= *ptr1 / *ptr2;
    NB: – There should be blank space between / and * in the multiplication and division operations because if we write /* together, then it will be considered as the beginning of a comment and the statement will fail.
      • Pointer variables cannot be added as ptr1 = ptr1 + ptr2 is not valid.
      • We can use relational operators properly with two/more pointers when they are correctly defined or declared. We can represent this as –
    ptr1 == ptr2;
    ptr1 < ptr2;
    ptr2 != ptr1;
        • These expressions are permissible and valid provided the pointers ptr1 and ptr2 refer to same and related variables. These comparisons are common in handling arrays.
      • Multiplication or division of a pointer with a constant value is not allowed. For example, ptr1 * ptr2 or ptr2 / 5 are invalid.
      • An invalid pointer reference occurs when a pointer’s value is referenced even though the pointer doesn’t point to a valid block. For example, if ptr1 and ptr2 are two pointers. If we say, ptr1 = ptr2 and when ptr2 is uninitialized. The pointer ptr1 will then become uninitialized as well, and any reference to *ptr1 is an invalid pointer reference.

    Array and Pointer

    • Array also behaves like as pointer i.e. An array lead the compiler to pick an address of base cell of an array to store a sequence of given values. The array name in this case is the address where the sequence of values starts.
    • For example, if ‘arr’ is supposed to be a one-dimensional array, then the address of the first array element can be written as &arr[0] or simply arr. Moreover, the address of the second array element can be written as &arr[1] or simply (arr+1).
    • In general, address of array element (i+1) can be expressed as either &arr[ i] or as (arr+ i). Thus, we have two different ways for writing the address of an array element. Here, &arr[ i] and (arr+ i) both represent the address of the ith element of arr, so arr[ i] and *(arr + i) both represent the contents of that address i.e., the value of ith element of arr.
    • It is not possible to assign an arbitrary address to an array name or to an array element. Thus, expressions such as arr, (arr+ i) and arr[ i] cannot appear on the left side of an assignment statement. Thus we cannot write a statement such as –
      &arr[0] = &arr[1];             //Invalid address assignment.
    • We can assign the value of one array element to another through a pointer, for example –
                   int *ptr;
                   ptr = &arr[0];
    arr[1] = *ptr;
    • In two dimensional array, for example –
      int arr[ 3 ][ 3 ] = {{10, 20, 30}, {40, 50, 60}, {70, 80, 90}};
      The compiler treats a two dimensional array as an array of arrays. As we know that a two dimensional array, array name(arr) represents the first row of 3-element array. Similarly, (arr + 1) points to the second row of 3-element array (i.e., row 1), (arr + 2) and so on. The value of second row elements can be obtained using, *(arr + 1), that refers to the entire row. Hence, row 1 is a one-dimensional array, (arr + 1) is actually a pointer to the first element in row 1. Now (*(arr + 1) + 2) is a pointer to display element/column 2 values (i.e., the third element) in row 1. Similarly, (*(arr + 2) + 1) means display element/column 1 values (i.e., the second element) in row 2.

    Array of Pointer

    • An array of pointer is a collection of addresses in the form of array.
    • Normally single/multidimensional array addresses can be stored in an array of pointers contiguously.
    • One dimensional array of pointer can be represented as –

    int *arr[5];

    • Two dimensional array of pointer can be represented as –

    int *arr[3][3];

    • Similarly, an n-dimensional array can be defined as (n-1)-dimensional array of pointers –
      syntax = data-type *arr[subscript 1] [subscript 2]…. [subscript n-1];

    Pointer and Strings

    • Like one-dimensional arrays, a string can be accessed via a pointer to the first character in the string.
    • The value of a string is the (constant) address of its first character. Thus, it is said that a string is a constant pointer.
    • A string can be declared as a character array or a variable of type char *. The declarations can be done as –
      char Str[ ] = “IGNOU”;
      char *Str= “IGNOU”;
      Here, above examples initialize a variable to the string “IGNOU”. The second declaration creates a pointer variable ‘Str’ that points to the first letter ‘I’ in the string “IGNOU” somewhere in memory. As we know that once the base address is obtained in the pointer variable Str, *Str would yield the value (IGNOU) at this address, which gets printed through, printf (“%s”, *Str);
    • Arrays may contain pointers i.e.we can form an array of strings, referred to as a string array. Consider the following declaration of a string array:

    char *fruits[ ] = {“Apple”, “Guava”, “Mango”, “Orange”, “Banana”};
    The *fruits[ ] of the declaration indicates an array of five elements. The char* of the declaration indicates that each element of array fruits is of type “pointer to char”. Thus, fruits[0] will point to Apple, fruits[ 1] will point to Guava, and so on.
    Thus, even though the array fruits is fixed in size, it provides access to character strings of any length. However, a specified amount of memory will have to be allocated for each string. for example  –

    fruits[ i ] = (char *) malloc(15 * sizeof (char));

    Click this link to see the Examples of Pointer and Strings

    Pointer and Function

    • We can pass pointer as arguments in a function as Pass by reference method.
    • In this method, when arguments are passed by reference (i.e. when a pointer is passed as an argument to a function), the address of a variable is passed. The contents of that address can be accessed freely, either in the called or calling function. Therefore, the function called by reference can change the value of the variable used in the call.
    • Using call by reference method we can make a function return more than one value at a time, which is not possible in the call by value method.
    • A function can also return a pointer to the calling program, it returns an int, a float or any other data type. To return a pointer, a function must explicitly mention in the calling program as well as in the function prototype.

    Click this link to see the examples of Pointer and Function

    Pointer and Structure

    • As we know that a pointer is a variable which points to the address of another variable of any data type such as 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. 
    • Pointer to structure can be represented as –
    struct student
    {
        char name[30];
        int rollno;
        int class;
        char course[30];
    };
    struct student stu;
    struct student *ptr;

             ptr=&stu;

    Click this link to see the examples of Pointer and Structure

    Types of Pointer

    • Wild pointer
      • Uninitialized pointers in the C code are known as Wild Pointers. These are a point to some arbitrary memory location and can cause bad program behavior or program crash.
    • Null pointer
      • When we assign a zero(0) value/NULL to a pointer of any type, then it becomes a Null pointer. This pointer doesn’t refer to any address of variable.
      • It is an exception to assign an integer value 0, which is sometimes used to indicate some special condition.
      • The address of null pointer results 0/zero on printing.
      • A macro is used to represent a null pointer. That macro goes under the name NULL.
      • Thus, a null pointer is declared as –
    int ptr = NULL;
    int ptr=0;
    • Dangling pointer
      • When there is a pointer pointing to a memory address of any variable, but after some time the variable was deleted from the memory location while keeping the pointer pointing to that location.
      • If a pointer is pointing any memory location, but meanwhile another pointer deletes the memory occupied by the first pointer while the first pointer still points to that memory location, the first pointer will be known as a dangling pointer. This problem is known as a dangling pointer problem.
      • Dangling pointer arises when an object is deleted without modifying the value of the pointer. The pointer points to the deallocated memory.
      • The problem of a dangling pointer can be overcome by assigning a NULL value to the dangling pointer.
    • Near pointer
      • A virtual address is composed of the selector and offset.
      • A near pointer doesn’t have explicit selector.
      • These are the non-standard keywords and implementation specific. These are irrelevant in a modern platform.
    • Far pointer
      • A pointer which can access all the 16 segments (whole residence memory) of RAM is known as far pointer. A far pointer is a 32-bit pointer that obtains information outside the memory in a given section.
      • A virtual address is composed of the selector and offset.
      • A far pointer have explicit selector.
      • When we perform pointer arithmetic on the far pointer, the selector is not modified.
      • These are the non-standard keywords and implementation specific. These are irrelevant in a modern platform.
    • Huge pointer
      • A virtual address is composed of the selector and offset.
      • A huge pointer have explicit selector.
      • When we perform pointer arithmetic on the huge pointer, the selector is modified.
      • These are the non-standard keywords and implementation specific. These are irrelevant in a modern platform.

    Use/Applications 

    The main use of pointers are –

    • Accessing Array Elements : Pointers are used for accessing information quickly stored in an array of integers and strings.
    • Dynamic Memory Allocation : Pointers are used/involved in allocation and de-allocation of memory during the execution of a program i.e. they are used to create dynamic data structures built up from blocks of memory allocated from the heap at run-time.
    • Call by Reference : C uses pointers to handle variable parameters passed to functions i.e. the pointers are used to pass a reference of a variable to other function for further processing.
    • Data Structures Creation : The pointers are used to construct different data structures as one of the main components in tree, graph, linked list, stack, queue etc.
    • Developing Software : The power of pointers is as a great tool used by expert programmers for developing system software, driver software etc.

    Loading

    Categories: C

    0 Comments

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    This site uses Akismet to reduce spam. Learn how your comment data is processed.