Circular Queue in C – Array Implementation with Modulo Wrap

A circular queue in C solves the main limitation of a linear queue: wasted array slots after dequeuing. In a linear queue, rear keeps advancing rightward; once it hits the end of the array, the queue reports “full” even if dequeued slots at the front are free. A circular queue wraps rear back to index 0 using modulo arithmetic, reusing those freed slots.

Linear Queue Problem vs Circular Queue Solution

Linear queue (SIZE=5) after enqueue ×5, dequeue ×3:
  [ _, _, 30, 40, 50 ]  rear=4 → isFull() = true
  Front slots 0,1 are free but unusable!

Circular queue — same operations:
  [ _, _, 30, 40, 50 ]  rear=4, front=2
  Next enqueue: rear = (4+1)%5 = 0  → slot 0 reused ✓

Circular Queue Program in C

#include <stdio.h>

#define SIZE 5

int queue[SIZE];
int front = -1, rear = -1;

int isFull(void)  { return (rear + 1) % SIZE == front; }
int isEmpty(void) { return front == -1; }

void enqueue(int val)
{
    if (isFull()) {
        printf("Circular queue overflow.\n");
        return;
    }
    if (front == -1) front = 0;       /* first insertion */
    rear = (rear + 1) % SIZE;
    queue[rear] = val;
    printf("Enqueued: %d\n", val);
}

int dequeue(void)
{
    int val;
    if (isEmpty()) {
        printf("Circular queue underflow.\n");
        return -1;
    }
    val = queue[front];
    if (front == rear)
        front = rear = -1;            /* queue becomes empty */
    else
        front = (front + 1) % SIZE;
    return val;
}

void display(void)
{
    int i;
    if (isEmpty()) { printf("Queue is empty.\n"); return; }
    printf("Front[%d] → ", front);
    i = front;
    while (1) {
        printf("%d ", queue[i]);
        if (i == rear) break;
        i = (i + 1) % SIZE;
    }
    printf("← Rear[%d]\n", rear);
}

int main(void)
{
    enqueue(10);
    enqueue(20);
    enqueue(30);
    enqueue(40);
    enqueue(50);   /* SIZE=5: this triggers overflow */
    display();

    printf("Dequeued: %d\n", dequeue());
    printf("Dequeued: %d\n", dequeue());
    enqueue(60);   /* wraps around to index 0 */
    enqueue(70);   /* wraps around to index 1 */
    display();

    return 0;
}

How to Compile and Run

gcc -Wall -o circqueue circqueue.c
./circqueue

Sample Output

Enqueued: 10
Enqueued: 20
Enqueued: 30
Enqueued: 40
Circular queue overflow.
Front[0] → 10 20 30 40 ← Rear[3]
Dequeued: 10
Dequeued: 20
Enqueued: 60
Enqueued: 70
Front[2] → 30 40 60 70 ← Rear[1]

Notice the last display: Rear[1] is at a lower index than Front[2] — the queue has wrapped around the array. This is impossible with a linear queue but normal for a circular one.

Step-by-Step Trace (SIZE = 5)

enqueue(10): front=0, rear=0  [10, _, _, _, _]
enqueue(20): front=0, rear=1  [10,20, _, _, _]
enqueue(30): front=0, rear=2  [10,20,30, _, _]
dequeue():   returns 10       front=1, rear=2  [_,20,30, _, _]
dequeue():   returns 20       front=2, rear=2  [_, _,30, _, _]
enqueue(40): rear=(2+1)%5=3   [_, _,30,40, _]
enqueue(50): rear=(3+1)%5=4   [_, _,30,40,50]
enqueue(60): rear=(4+1)%5=0   [60,_,30,40,50]  ← wraps!
enqueue(70): rear=(0+1)%5=1   [60,70,30,40,50]
isFull check: (1+1)%5=2 == front=2  → true, queue is full

Why (rear + 1) % SIZE == front for isFull

One slot is deliberately kept empty to distinguish between “full” and “empty” (both would have front == rear otherwise). A SIZE-5 circular queue holds at most 4 elements. If you need all 5 slots, add a separate count variable.

Time and Space Complexity

Operation Time Space
ENQUEUE O(1) O(1)
DEQUEUE O(1) O(1)
Total storage O(n)

What This Program Teaches

  • The modulo wrap: (index + 1) % SIZE turns a linear array into a ring — the fundamental circular buffer pattern used in OS kernels, audio buffers, and network packet queues
  • The full/empty ambiguity: without a sentinel slot or a counter, front == rear is true for both full and empty — one slot is sacrificed to resolve this cleanly
  • Why circular queues are preferred over linear queues for fixed-size buffers: full utilization of the allocated memory

Related Programs


As an Amazon Associate we earn from qualifying purchases.

Recommended Book

Arrays and modulo arithmetic are covered from first principles in The C Programming Language by Kernighan & Ritchie. Also on Amazon.com.

4 comments on “Circular Queue in C – Array Implementation with Modulo Wrap

  • In a linear queue, a new element is inserted at the end of the list, while a deletion is made at the front of the list. The front and rear
    ends are responsible for tracking the queue status. A queue can have a finite number of elements, which is predefined.
    Every new insertion must pass a "queue overflow" test, and likewise, prior to a deletion, a "queue underflow" test must be passed.
    "Queue overflow" checks whether that there is space for the insertion, and "queue underflow" makes sure there are elements waiting to be deleted and the
    queue is not already empty.
    In linear queue if the size is defined, and if you once got the overflow condition, then you can't insert the items even if you delete the items from the queue…..
    see the link and try with different inputs
    http://www.c-program-example.com/2011/10/c-program-for-simplelinear-queue.html

    In a circular queue, insertions and deletions can happen at any position in the queue and not necessarily in a sequential order.
    In circular queue you can add and delete the queue elements up to the size of the queue… i.e in the above program 5.

    You try both the programs i.e linear and circular… you can easily finds which one is the circular!!!

    Reply

Leave a Reply

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

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>