# Circular Buffer ###### tags: `C LANGUAGE` `ring buffer` `circular buffer` <style> .blue { color: blue; } .bgblue { color: blue; font-size: 24px; font-weight: bold; } .red { color: red; font-size: 24px; font-weight: bold; } h1 {text-align: center;} </style> Author: CrazyMonkey email: kccddb@gmail.com Date: 20220726 Copyright: CC BY-NC-SA ![](https://i.imgur.com/aAdDPB3.jpg) 另一重要的 [circular buffer](https://en.wikipedia.org/wiki/Circular_buffer) 運用, 尤其是記憶體受限時, 例如 單晶片, embedded system 或資料變動快速與大量時(**使用circular buffer 不需要 經常 malloc, free, 如此可減少 OS 進行garbage collection! )** ![](https://i.imgur.com/acdJk6f.jpg) Reference source code **cring.h** ```c= typedef struct _ring_buffer { void *buffer; // data buffer void *buffer_end; // end of data buffer size_t capacity; // maximum number of items in the buffer size_t count; // number of items in the buffer size_t sz; // size of each item in the buffer void *head; // pointer to head void *tail; // pointer to tail int (*push)(struct _ring_buffer *pthis,const void *item); int (*pop)(struct _ring_buffer *ring, void *item); } ring_buffer; /* byte acces ring_init( size_t capacity, 1); */ ring_buffer * ring_init( size_t capacity, size_t sz); void ring_exit(ring_buffer *ring); ``` **cring.c** ```c= #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include "cring.h" static int ring_push(ring_buffer *ring, const void *item) { if(ring->count == ring->capacity){ return 0; } memcpy(ring->head, item, ring->sz); ring->head = (unsigned char*)ring->head + ring->sz; if(ring->head == ring->buffer_end) ring->head = ring->buffer; ring->count++; return ring->count; } static int ring_pop(ring_buffer *ring, void *item) { if(ring->count == 0){ // handle error return 0; } memcpy(item, ring->tail, ring->sz); ring->tail = (unsigned char*)ring->tail + ring->sz; if(ring->tail == ring->buffer_end) ring->tail = ring->buffer; ring->count--; return ring->count; } ring_buffer * ring_init( size_t capacity, size_t sz) { ring_buffer *ring; ring=malloc(sizeof(ring_buffer)); if(ring==NULL)return NULL; ring->buffer = malloc(capacity * sz); if(ring->buffer == NULL){ free(ring); return NULL; } ring->buffer_end = (unsigned char *)ring->buffer + capacity * sz; ring->capacity = capacity; ring->count = 0; ring->sz = sz; ring->head = ring->buffer; ring->tail = ring->buffer; ring->push=ring_push; ring->pop=ring_pop; } void ring_exit(ring_buffer *ring) { if(ring){ free(ring->buffer); free(ring); } } ``` HW.![](https://i.imgur.com/Xs6nrjz.jpg)