Different Types of Pointers in C

This article is the continuation of the Series on the C programming tutorial and carries the discussion on C language programming and its implementation. It aims to provide easy and practical examples for understanding the C program. In our last article, we saw the pointer’s advanced topics in C programming. 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.


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 pointers in C. There are many different types of Pointers in C.

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.


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


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*/


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 pointer like a 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 a pointer which is applicable to all types of pointers. For example return type of the malloc function is a generic pointer because it can dynamically allocate the memory space to store an integer, float, structure, etc. hence we can typecast its return type to the appropriate pointer type.


void *<data type>;


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 point 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


Return Local Variable in Function Call

char* func()
   char str[10];
//returned pointer points to str which has gone out of scope.

Variable goes Out of Scope


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));
*c = 3; //writing to freed location!

Avoiding dangling pointer errors

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


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

int *c = malloc(sizeof(int));
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.
  • A wild pointer is also called a 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;


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 the 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 very 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.



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

Output: 2

Far Pointers

  • The pointer that 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.



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

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


Output: 4

In that 4bytes,

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

int main()
    int x=100;
    int far *ptr;
    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.


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 that can point or access whole the residence memory of RAM i.e. which can access all 16 segments is known as a huge pointer.
  • The size of a huge pointer is 4 bytes or 32-bit


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 an 8085 microprocessor in which the physical address of memory is represented in 20 bits. Conversion of 4 bytes or 32-bit huge addresses into 20-bit actual physical addresses 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 pointers 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 an actual physical address, security, etc. c has introduced three types of pointers i.e. near, far, and huge pointer.

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

In our next article, we will see callback functions in C programming.

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
STM32F7 Bootloader TutorialsRaspberry PI Pico Tutorials
STM32F103 Bootloader TutorialsRT-Thread RTOS Tutorials
Zephyr RTOS Tutorials - STM32Zephyr RTOS Tutorials - ESP32
AUTOSAR TutorialsUDS Protocol Tutorials
Product ReviewsSTM32 MikroC Bootloader Tutorial
VHDL Tutorials
Notify of

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

Inline Feedbacks
View all comments
Table of Contents