我正在尝试进入C程序,我认为尝试实现循环缓冲区是个好主意。
我像这样定义了我的结构:
typedef struct
{
int8_t* buffer;
int8_t* buffer_end;
int8_t* data_start;
int8_t* data_end;
int64_t count;
int64_t size;
} ring_buffer;和职能:
void RB_init(ring_buffer* rb, int64_t size)
{
rb->buffer = malloc(sizeof(int8_t) * size);
rb->buffer_end = rb->buffer + size;
rb->size = size;
rb->data_start = rb->buffer;
rb->data_end = rb->buffer;
rb->count = 0;
}
void RB_free(ring_buffer* rb)
{
free(rb->buffer);
}
bool RB_push(ring_buffer* rb, int8_t data)
{
if (rb == NULL || rb->buffer == NULL)
return false;
*rb->data_end = data;
rb->data_end++;
if (rb->data_end == rb->buffer_end)
rb->data_end = rb->buffer;
if (RB_full(rb)) {
if ((rb->data_start + 1) == rb->buffer_end)
rb->data_start = rb->buffer;
else
rb->data_start++;
} else {
rb->count++;
}
return true;
}
int8_t RB_pop(ring_buffer* rb)
{
if (rb == NULL || rb->buffer == NULL)
return false;
int8_t data = *rb->data_start;
rb->data_start++;
if (rb->data_start == rb->buffer_end)
rb->data_start = rb->buffer;
rb->count--;
return data;
}
bool RB_full(ring_buffer* rb)
{
return rb->count == rb->size;
}我做了一些测试,看起来效果很好。你能提出一些改进建议吗?
发布于 2013-01-14 18:29:36
这个看起来不错。它的可读性很强,而且可能很快。
有时,环形缓冲区包装是通过使用以下类型的剩余部分和偏移来实现的:
end_offset = (end_offset + 1) % size;但我喜欢你的做法,没有补偿和分裂。
一些小发现:
NULL指针在RB_pop中检查可以防止分段错误,但调用方将获得返回值为零。因此调用方不会知道零是错误还是成功的结果。int8_t RB_pop(ring_buffer* rb) {如果(rb == NULL \ rb->buffer == NULL)返回false;RB_pop和RB_push都进行检查:rb == NULL。也许其他功能也应该这样做。发布于 2014-04-12 00:01:21
我同意@User1 1关于RB_pop()的观点,并想在其中添加以下内容:
为了防止函数返回false的意外返回值,您应该使函数void并有第二个参数data。如果第一个条件语句是return,这也允许您尽早使用false。
void RB_pop(ring_buffer* rb, int8_t* data)
{
if (rb == NULL || rb->buffer == NULL)
return;
// update data parameter...
}发布于 2018-11-28 11:53:52
你没有在pop函数中检出count。如果缓冲区为空,您将返回垃圾,同时计数也将为负数。
https://codereview.stackexchange.com/questions/16468
复制相似问题