Monday, 8 June 2020

Section 4a Pointers in C

What is a pointer?

A pointer is a variable that stores the address of another variable.
This variable can be of type int, char, array, function, or any other pointer.


The unary operator & (ampersand) returns the address of a variable
For example &x gives us address of variable x.

ex:
int main()
{
    int x;
 
    // To print address of x
    printf("%p", &x);
 
    return 0;
}

The unary * (Asterisk) operator  is used for two things :

a) To declare a pointer variable: The pointer in c language is declared  using * (asterisk symbol)

int  *height;  --> pointer variable height holds the address  of a integer variable
char  *alphabet;  --> pointer holds the  address of a character variable
 Example:
#include <stdio.h>
int main()
{
    int x = 10; //declare integer variable
 
    int *ptr;  // pointer to an integer variable
 
    ptr = &x;  // get the address of x and assign it to pointer variable
 
    return 0;
}

b) as indirection pointer used to de-reference a pointer.

To access the value stored in the address,  the unary operator (*)  is used. It  returns the value of the variable located at the address specified by its operand. This is also called Dereferencing.

Example:

// Print the value at address stored in ptr. Value stored is value of variable "x"

    printf("Value of x = %d\n", *ptr);

reference: testptr1.c


Pointer Arithmetic

C language provides a set of operators to perform arithmetic and comparison of memory addresses. Pointer arithmetic and comparison in C is supported by following operators -
  • Increment and decrement ++ and --
  • Addition and Subtraction + and -
  • Comparison <, >, <=, >=, ==, != 
incrementing a pointer will cause the pointer to point to a memory location skipping N bytes from current pointed memory location. Where N is size of pointer data type.

Similarly, decrement operator returns the previous address pointed by the pointer. The returned address is the difference of current pointed address and size of pointer data type.

Consider that ptr is an integer pointer which points to the address 1000. Assuming 32-bit integers, perform the increment operator on pointer.

Pointer increment and decrement operator
 
If ptr points to a character whose address is 1000, then the above operation will point to the location 1001 because the next character will be available at 1001.

Consider the operation ptr++

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.

ref testptr2.c

Pointer Addition and Subtraction

Pointer increment operation increments pointer by one. Causing it to point to a memory location skipping N bytes (where N is size of pointer data type).

increment operation is equivalent to addition by one. Suppose an integer pointer int * ptr. Now, ptr++ is equivalent to ptr = ptr + 1.

Similarly, you can add or subtract any integer value to a pointer.
Adding K to a pointer causes it to point to a memory location skipping K * N bytes. Where K is a constant integer and N is size of pointer data type.

ref testptr3.c 

Pointer Comparison

Pointer comparison compares two pointer addresses to which they point to, instead of comparing their values.

1) Suppose we want to test if 2 pointers point to the same location

int x  = 10;

int *ptr1 = &x;
int *ptr2 = &x;

if ( ptr1 == ptr2 )
{}

2) Suppose we want to check if the pointer is within array range

int x[10];
int *ptr = &x[0];

ptr < &x[10];   // Check if the ptr is within the array range


ref testptr4.c  

Pointer to pointer

A pointer to a pointer is a form of multiple indirection.A pointer contains the address of a variable. In the case of pointer to a pointer, the first pointer contains the address of the second pointer. The second pointer  points to the location that contains the actual value.

This is also referred to as double pointer.

syntax:

datatype  **ptr_varble_name

Example to initialize and use double pointer

int num;

int *ptr = &num;
int  **dpte = &ptr;

ref testptr5.c  

Pointers and Array

An array name is a constant pointer to the first element of the array.

consider the following:

int sal[10];

In this declaration, sal is a pointer to sal[0], which is the address of the 0th element of the array.

So , this fragment of code is true:

int *ptr;

int sal[10];

ptr = sal; // This is the address of the 0th element of the array ie &sal[0]
Once you get the address of the first element in 'ptr', you can access the array elements using *ptr, *(ptr+1), *(ptr+2) and so on. 

Reference

int sal[5];
int *ptr = sal;        // Integer pointer pointing at sal[0]

sal[0] = 100;         // Assigns 100 to sal[0]
ptr++;                  // ptr now points at sal[1]
ptr--;                     // ptr now points back at sal[0]

*(ptr + 4) = 400;  // Assigns 400 to sal[4]. Hence (ptr + 4) will point at sal[4]

*(sal + 0) = 10;        // Assigns 10 to sal[0]

Note: Array name ie sal behaves as a constant and cannot be modified ie operations like sal++ ie ( sal = sal + 1) is not possible

ref: ptrarray.c

Constant Pointer and pointer to constant

constant pointer

 This is a pointer variable whose value cannot be changed throughout the program, ie the memory pointed to by  the pointer variable cannot be changed. However the value stored in the memory location can be changed
 
example declaration

int num1, num2;
int * const cnst_ptr = &num1; 

num1 = 10;

num2 = 20;

cnst_ptr = &num2 // not allowed

*cnst_ptr = 200 ; // allowed
 
pointer to constant
The pointer points to a memory location whose value cannot be changed.

int num = 10;
const int * ptr1 = &num;    // Pointer to constant

* ptr1 = 100 //not allowed

constant pointer to pointer

 It is a pointer that does not allow modification of pointer value as well as value pointed by the pointer.

Example:

int num4 = 100;
int num5 = 600;

const int * const ptr3 = &num4;

ptr3 = &num5; // This will throw error, pointer value cannot be changed
*ptr3 = 800; // This will throw error, value pointed to by the pointer cannot be changed

ref constptr.c

Void Pointer , Null Pointer

Void Pointer

A void pointer is a pointer that has no associated data type with it.
A void pointer can hold address of any type and can be type casted to any type ie it can point to any datatype. It is also know as type less pointer
A void pointer is a type

ref voidptr.c

Null Pointer
A null pointer is a value.  It is a special reserved value used to indicate that the pointer is not pointing to anything conceptually
A Null Pointer is a pointer that does not point to any memory location.

Conceptually, when a pointer  has a null value , it is not pointing anywhere.

Usually a null pointer points to:

    the address 0 or an address that's illegal for user code to access

The null pointer basically stores the Null value
When a NULL value is assigned to the pointer, then it is considered as a Null pointer.

When we use a malloc() function to allocate memory, if the function is unable to allocate memory , it returns a null pointer.

ref nullptr.c

Dangling Pointer

A pointer  pointing to a memory  that is freed or deallocated  is a dangling pointer.
The pointer still points to the memory location of the de-allocated memory.

The  following are the 3 situations in which a pointer becomes a dangling .

1. Deallocation of memory:
    When the memory pointed to by the pointer is deallocated , then the pointer becomes a dangling pointer
   
   
2. When a variable goes out of scope, the pointer pointing to the variable becomes
    a dangling pointer

3. A pointer to a variable in a function call becomes a dangling pointer after the execution of the function call.

Ref : danglptr.c danglptr1.c








No comments:

Post a Comment