Different Types of Pointers in C

In our previous two tutorials, we have seen What are the pointers and their applications. In this tutorial, we are going to see Different types of pointers in c.

You can also read, embedded interview topics, compilation steps, and memory layout in C.

Prerequisites

Before starting our topic, I would recommend you to read these pointer topics.

Different Types of Pointers in C

Pointers are the variables that are used to store the address of another variable. We can use this pointer to point to the address of another variable or function or another pointer. That we know already. If you don’t know, please read Prerequisites.

Now we will talk about types of the pointer in C. There are many different types of Pointers in C.

  • NULL Pointer
  • Void pointer or Generic Pointers
  • Dangling Pointer
  • Wild Pointer or Bad Pointer
  • Near Pointer (old method, Not useful for nowadays)
  • Far Pointer (old method, Not useful for nowadays)
  • Huge Pointers (old method, Not useful for nowadays)

NULL Pointer

  • A NULL pointer is a pointer that is pointing to nothing, i.e. it is assigned a null value.
  • In case, if you don’t have an address to be assigned to a pointer then you can simply use NULL. (It is considered a good practice to set it to null.)
  • The pointer which is initialized with NULL value is considered as a NULL pointer.
  • NULL is a macro constant defined in the following header files
    • stdio.h
    • alloc.h
    • mem.h
    • stddef.h
    • stdlib.h
  • Every pointer type i.e int *, char * each has a null pointer value.

Syntax

<data type> *<variable name> = NULL;

Example

int *ptr = NULL;
char *ptr = '\0';
float *ptr  = (float *)0;
double *ptr = NULL;

You can check the pointer is NULL or not by using the below snippet.

if(ptr != NULL) {
    /*Pointer is not NULL*/
} else {
    /*Pointer is NULL*/
}

Note:

A null pointer is conceptually different from an uninitialized pointer. A null pointer is known not to point to any object or function; an uninitialized pointer might point anywhere. An uninitialized pointer stores an undefined value.

Void Pointer or Generic Pointers

  • A void pointer is one that does not have any data type associated with it, i.e. it can be assigned a value of any type.
  • It is a C convention for a raw address. It is capable of storing addresses of any data type.
  • This is very useful when you want a pointer to point to data of different types at different times.
  • We cannot dereference the generic pointer.
  • The generic pointer can hold any type of pointers like char pointer, struct pointer, an array of the pointer, etc without any typecasting.
  • Any type of pointer can hold a generic pointer without any typecasting.
  • Generic pointers are used when we want to return such pointer which is applicable to all types of pointers. For example return type of malloc function is a generic pointer because it can dynamically allocate the memory space to stores an integer, float, structure, etc. hence we can typecast its return type to the appropriate pointer type.

Syntax

void *<data type>;

Example

void *ptr;  //void pointer
int a; 
char c;
ptr = &a; //ptr changes to integer pointer as address of integer is assigned to it
ptr = &c; //ptr changes to character pointer as address of character is assigned to it

Dangling Pointer

  • Dangling pointers are pointers that pointing to a memory location that has been deleted (or freed).
  • Dangling pointers arise during object destruction, when an object that has an incoming reference is deleted or deallocated, without modifying the value of the pointer, so that the pointer still points to the memory location of the deallocated memory.

Causes of dangling pointers

  1. Return Local Variable in Function Call

  2. Variable goes Out of Scope

  3. Accessing the De-allocating or free variable memory

Example

Return Local Variable in Function Call

char* func()
{
   char str[10];
   strcpy(str,"Hello!");
   return(str); 
}
//returned pointer points to str which has gone out of scope.

Variable goes Out of Scope

#include<stdio.h>

int main()
{
    char **strPtr;
    {
        char *str = "Hello!";
        strPtr = &str;
    }
    // str falls out of scope 
    // strPtr is now a dangling pointer 
    printf("%s", *strPtr);
}

Accessing the De-allocating or free variable memory

int *c = malloc(sizeof(int));
free(c);
*c = 3; //writing to freed location!

Avoiding dangling pointer errors

  • We can avoid the dangling pointer errors by initializing the pointer to NULL after de-allocating memory, so that pointer will be no longer dangling.
  • Assigning NULL value means the pointer is not pointing to any memory location. See below snippet to avoid dangling pointer.

Note:

In some compiler, you may get a warning message returning the address of a local variable or temporary.

int *c = malloc(sizeof(int));
free(c);
c = NULL;

Wild Pointer or Bad Pointer

  • A pointer that has not been initialized to anything till its first use (not even NULL) is known as a wild pointer. The pointer may be initialized to a non-NULL garbage value that may not be a valid address.
  • Wild pointer is also called Bad pointer because without assigning any variable address, it points to the memory location.

int main()
{
    int *ptr;  /* wild pointer */
 
    int x = 10;
 
    // ptr is not a wild pointer now
    ptr = &x;
 
    return 0;
}

Note:

We can initialize a pointer at the point of a declaration by the address of some object/variable or by NULL;

Old method Pointers

In TURBO C there are three types of pointers. TURBO C works under DOS operating system which is based on an 8085 microprocessor. These are some old concepts used in 16-bit intel architectures in the days of MS-DOS, not much useful anymore.

Near Pointers

  • Near pointer is used to store 16-bit addresses means within the current segment on a 16-bit machine. The limitation is that we can only access 64kb of data at a time.
  • That is near pointer cannot access beyond the data segment like graphics video memory, text video memory, etc.
  • The size of the near pointer is two bytes.
  • With help of keyword near, we can make any pointer a near pointer.

Example

#include<stdio.h>

int main()
{
     int x=25;
     int near* ptr;
     ptr=&x;
     printf(“%d”,sizeof ptr);
     return 0;
}

Output: 2

Far Pointers

  • The pointer which can point or access whole the residence memory of RAM, i.e., which can access all 16 segments is known as the far pointer.
  • The size of the far pointer is 4 bytes or 32 bit.

Example

#include<stdio.h>

int main()
{
    int x=10;
    int far *ptr;

    ptr=&x;
    printf("%d",sizeof ptr);
    return 0;

}

Output: 4

In that 4bytes,

  • First 16 bit stores: Segment number
  • Next 16 bit stores: Offset address

#include<stdio.h>

int main()
{
    int x=100;
    int far *ptr;
    ptr=&x;
    printf("%Fp",ptr);  //%Fp is used for print offset and segment address of pointer in printf function in hexadecimal number format
    return 0;
}

Output: 8FD8:FFF4

Here 8FD8 is the segment address and FFF4 is the offset address in hexadecimal number format.

Note:

We cannot guess what will be offset address, segment address, and far address of any far pointer. These addresses are decided by the operating system.

Limitation of far pointer

We cannot change or modify the segment address of the given far address by applying any arithmetic operation on it. That is by using the arithmetic operator we cannot jump from one segment to another segment. If you will increment the far address beyond the maximum value of its offset address instead of incrementing the segment address it will repeat its offset address in cyclic order.

Huge Pointers

  • The pointer which can point or access whole the residence memory of RAM i.e. which can access all the 16 segments is known as a huge pointer.
  • The size of a huge pointer is 4 byte or 32 bit

Example

#include<stdio.h>
int main()
{
    char huge * far *p;
    printf("%d %d %d",sizeof(p),sizeof(*p),sizeof(**p));
    return 0;
}

Output: 4 4 1

Normalization of huge pointer

Turbo C compiler is based on 8085 microprocessor in which physical address of memory is represented in 20 bit. Conversion of 4 bytes or 32-bit huge address into 20-bit actual physical address is known as normalization.

Note: If you will increment a huge pointer it will increment both offset and segment address unlike to far pointer which only increments offset address. So, if you have little knowledge about huge pointer and you are using huge pointer then you can easily access and modify the IVT, device driver memory, video memory, etc. This might be dangerous for your computer.

Why there are three types of pointer in the Turbo c compiler?

Turbo c compiler is based on Dos operating system which is based on 8085 microprocessors. In the 8085 microprocessor, the actual physical address is represented in 20 bits. But there are not any pointers that can point 20-bit address. Considering the simplicity of calculations, access to actual physical address, security, etc. c has introduced three types of pointer i.e. near, far and huge pointer.

You can also see the Important interview topics in C Program Here.

You can also read the below tutorials.

Linux Device Driver TutorialsC Programming Tutorials
FreeRTOS TutorialsNuttX RTOS Tutorials
RTX RTOS TutorialsInterrupts Basics
I2C Protocol – Part 1 (Basics)I2C Protocol – Part 2 (Advanced Topics)
STM32 TutorialsLPC2148 (ARM7) Tutorials
PIC16F877A Tutorials8051 Tutorials
Unit Testing in C TutorialsESP32-IDF Tutorials
Raspberry Pi TutorialsEmbedded Interview Topics
Reset Sequence in ARM Cortex-M4BLE Basics
VIC and NVIC in ARMSPI – Serial Peripheral Interface Protocol
Bootloader TutorialsRaspberry PI Pico Tutorials
5 4 votes
Article Rating
Subscribe
Notify of
guest

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

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x