首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >单个类型的环缓冲区处理程序

单个类型的环缓冲区处理程序
EN

Stack Overflow用户
提问于 2019-07-31 06:39:00
回答 1查看 53关注 0票数 1

我想构建一个环形缓冲区API,但是与其在API本身中使用malloc()动态创建缓冲区,不如传递已经存在的变量类型数组(uint8_t、uint16_t等)。

因此,我认为实现这一目标的最佳方法是声明一个包含所有所需信息和所需API函数的结构。

代码语言:javascript
复制
typedef struct ring_buffer {
    void * buffer;
    uint8_t element_size;
    size_t head;
    size_t tail;
    size_t max;
    bool full;
} ring_buffer_t;

ring_buffer_t buf_init(void * buffer, uint8_t element_size, size_t max);
void buf_add(ring_buffer_t * handle, uint8_t element);
bool buf_is_emtpy(ring_buffer_t * handle);
void* buf_pop(ring_buffer_t * handle);

ring_buffer_t buf_init(void * buffer, uint8_t element_size, size_t max){
    return (ring_buffer_t){.buffer = buffer, .element_size = 2, .head=0, .tail=0, .max=64, .full=false};
}

void buf_add(ring_buffer_t * handle, const uint8_t element){
    if(handle->head == handle->max){
        handle->head = 0;
    } 
    printf("adding %d at position %d\n", element, (uint8_t)handle->head);
    handle->buffer[handle->head] = element;
    handle->head += handle->element_size;
}

void* buf_pop(ring_buffer_t * handle){
    void* ret;
    if(handle->tail < handle->head-1){
        printf("Tail is at position %d\n", (uint8_t)handle->tail);
        ret = &handle->buffer[handle->tail];
        handle->tail += handle->element_size;
    } else {
        printf("Tail is at position %d\n", (uint8_t)handle->tail);
        ret = &handle->buffer[handle->tail];
    }
    return ret;
}

bool buf_is_emtpy(ring_buffer_t * handle){
    if(handle->head == handle->tail){
        return true;
    } else {
        return false;
    }
}

但这并不是无效的*似乎不是正确的事情来处理这个问题。我如何处理指针,我知道在我创建结构时的大小?因为在buf_add()中,为了添加element,我需要将handle->buffer转换成正确的指针类型。

怎样才是解决这一问题的正确办法?

根据给出的答案,我改变了行文

handle->buffer[handle->head] = element;

memcpy(&handle->buffer[handle->head], element, handle->element_size);

到目前为止,什么是有效的,但仍然给我一个警告,我是dereferencing 'void *' pointer --当然是这样,但是在这种情况下,正确的取消引用会是什么样子呢?

EN

回答 1

Stack Overflow用户

发布于 2019-07-31 06:54:32

看看memcpy()和朋友们。由于不能提供类型时不能使用简单的赋值,所以需要复制非类型化的存储块。

请尽可能提高编译命令的警告级别。你提供的消息来源有一些怪癖。;-)

编辑1

怪人发现:

GCC 8.1.0 (MinGW 64位)添加后用-Wall -Wextra报告的警告

代码语言:javascript
复制
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

buf_init有未使用的参数,element_sizemax。源使用常量。

还有关于取消引用void*指针和分配要添加的元素的警告。当然,因为消息来源是不正确的。

我也会使用size_t作为element_size的类型,因为它代表一个大小。

GCC和-pedantic一起对指针算法提出警告。但我们是故意的。

编辑2

有关取消引用void*指针的警告是正确的,因此请替换

代码语言:javascript
复制
&handle->buffer[offset]

通过这个

代码语言:javascript
复制
handle->buffer + offset

您必须实现“手工”的地址计算。

如果使用索引而不是偏移量,则必须按元素的大小添加乘法:

代码语言:javascript
复制
handle->buffer + index * handle->element_size

另一个问题:memcpy()需要一个指针作为第二个参数..。这是我的建议:

代码语言:javascript
复制
void buf_add(ring_buffer_t * handle, void *element) {
    if (handle->head == handle->max) {
        handle->head = 0;
    } 
    memcpy(handle->buffer + handle->head, element, handle->element_size);
    handle->head += handle->element_size;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57284668

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档