【问题标题】:C Basic ring buffer issueC基本环形缓冲区问题
【发布时间】:2016-03-08 14:05:04
【问题描述】:

我在尝试制作的基本环形缓冲区存在问题。 我似乎无法让它正确环绕。 当我达到元素数 = buffer_length 时,行为变得不可预测,并且在调试器中它只会显示第一个 * 元素。

谁能看到我遗漏的明显错误。

提前致谢。

#include "stdafx.h"
#include <stdio.h>
#include <string.h>

#define BUFFER_LENGTH 8

typedef struct circular_buffer
{
    float buffer[BUFFER_LENGTH];
    float *buffer_end;
    float *head;
    float *tail;
    size_t count;
} circular_buffer;

circular_buffer buffer;

void cb_init(circular_buffer *cb)
{
    memset(cb->buffer, 0, BUFFER_LENGTH * sizeof(float));

    cb->buffer_end = (float *)cb->buffer + BUFFER_LENGTH * sizeof(float);
    cb->count = 0;
    cb->head = cb->buffer;
    cb->tail = cb->buffer;
}

void cb_push_back(circular_buffer *cb, float item)
{
    *cb->head = item;
    cb->head = (float *)cb->head++;
    if (cb->head == cb->buffer_end)
        cb->head = &cb->buffer[0];
    cb->count++;
}

float cb_pop_front(circular_buffer *cb)
{
    float item = 0;
    item = *cb->tail;
    cb->tail = (float*)cb->tail++;
    if (cb->tail == cb->buffer_end)
        cb->tail = &cb->buffer[0];
    cb->count--;
    return item;
}

float cb_peek_front(circular_buffer *cb, size_t pos)
{
    float *arrPos;
    size_t i = 0;
    do
    {
        arrPos = (float*)cb->tail + i;
        if (arrPos == cb->buffer_end)
            arrPos = cb->buffer;
        i++;
    } while (i <= pos);

    return *arrPos;

}

int _tmain(int argc, _TCHAR* argv[])
{
    cb_init(&buffer);

    cb_push_back(&buffer, 5);
    printf("%f\n",cb_pop_front(&buffer));
    cb_push_back(&buffer, 6);
    printf("%f\n", cb_pop_front(&buffer));
    cb_push_back(&buffer, 7);
    printf("%f\n", cb_pop_front(&buffer));
    cb_push_back(&buffer, 8);
    printf("%f\n", cb_pop_front(&buffer));
    cb_push_back(&buffer, 9);
    printf("%f\n", cb_pop_front(&buffer));
    cb_push_back(&buffer, 10);
    printf("%f\n", cb_pop_front(&buffer));
    cb_push_back(&buffer, 11);
    printf("%f\n", cb_pop_front(&buffer));
    cb_push_back(&buffer, 12);
    printf("%f\n", cb_pop_front(&buffer));

    // stops working here
    cb_push_back(&buffer, 13);
    printf("%f\n", cb_pop_front(&buffer));

    cb_push_back(&buffer, 14);
    printf("%f\n", cb_pop_front(&buffer));


    return 0;
}

【问题讨论】:

  • 为什么不将缓冲区视为一个数组并使用索引而不是指针?然后索引在前进时用index = (index + 1) % BUFFER_LENGTH 包装,或者在向后移动时用index = (index + BUFFER_LENGTH - 1) % BUFFER_LENGTH 包装。
  • 您不会在输入上测试“缓冲区已满”或在输出上测试“缓冲区不足”。你在那里做的唯一测试是“缓冲循环”。此外,拥有“head”、“tail”“count”有些多余。
  • cb-&gt;head = (float *)cb-&gt;head++; 此处未定义行为。为什么要从浮点数转换为浮点数?

标签: c buffer ring


【解决方案1】:

这个

cb->buffer_end = (float *)cb->buffer + BUFFER_LENGTH * sizeof(float);

不会如你所愿。

改成

cb->buffer_end = cb->buffer + BUFFER_LENGTH;

让它指向缓冲区的最后一个元素。


也只需将所有那些无用的强制转换为(float *)


另外你想替换

cb->head = (float *)cb->head++;

很简单

cb->head++;

cb->tail = (float*)cb->tail++;

通过

cb->tail++;

【讨论】:

  • 似乎足以解决 OP 代码中的问题。如果投反对票的人发表评论,那就太好了。
  • @ManosNikolaidis,不是我,但反对意见是在答案的初稿上,然后被暂时删除。
【解决方案2】:

在使用指针算法时,您不正确地考虑了元素的大小。例如

bufpointer += 1;

前进到下一个元素,就像你对数组索引所做的那样,你也不需要考虑每个元素的大小。所以

cb->buffer_end = (float *)cb->buffer + BUFFER_LENGTH * sizeof(float);

变成

cb->buffer_end = cb->buffer + BUFFER_LENGTH;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-04
    • 2011-04-25
    • 2019-09-27
    • 2012-09-12
    • 1970-01-01
    • 1970-01-01
    • 2018-10-29
    相关资源
    最近更新 更多