C语言实现一个缓冲区
FIFO(First In, First Out,先进先出队列)可以想象成一个 排队打饭 的场景,最先排队的人最先打到饭,后面来的人只能排在后面。
FIFO 里两个最重要的“指针”
- 写指针(write_index)负责存数据,就像打饭的窗口,给排队的人装饭。
- 读指针(read_index) 负责取数据,就像学生排队领饭,最先排队的最先拿到饭。
数据写入 FIFO(打饭窗口装饭)
每次有新的数据(饭),就存入 FIFO(放在队伍的最后)。写指针 write_index 向前移动,表示新的数据存进来了。如果饭盒满了(FIFO 满),就不能再装饭了,得等人先吃(读取数据)。
数据读取 FIFO(学生排队打饭)
FIFO 里有数据时,读指针 read_index 取出最早存入的数据。
取完数据后,读指针向前移动,准备读取下一个数据。如果队伍里没人(FIFO 为空),就没数据可读了!
FIFO 什么时候需要清空?
如果打饭的学生全都吃完了,队伍为空(FIFO 为空),指针会指向同一个位置。如果不清理饭盒(FIFO 满了),就不能继续装饭(写入新数据),需要“清空”队伍重新开始。
在程序里,我们可以用 fifo_flush() 来清空 FIFO,重置指针。
代码语言:javascript代码运行次数:0运行复制typedef struct {
uint8_t buffer[256]; // 存放数据(饭盒)
uint16_t write_index; // 写入指针(打饭窗口)
uint16_t read_index; // 读取指针(学生排队领饭)
uint16_t count; // 当前存放了多少数据(队伍长度)
} FIFO_t;
- buffer[256]就是 256 个饭盒,用来存数据。
- write_index负责装饭(存数据)。
- read_index负责拿饭(取数据)。
- count记录当前队伍里有多少人(存了多少数据)。
void fifo_init(FIFO_t *fifo) {
fifo->write_index = 0;
fifo->read_index = 0;
fifo->count = 0;
}
刚开始都清0
代码语言:javascript代码运行次数:0运行复制bool fifo_write(FIFO_t *fifo, uint8_t data) {
if (fifo->count == 256) return false; // 饭盒满了,不能再存数据
fifo->buffer[fifo->write_index] = data; // 把数据存入 FIFO
fifo->write_index = (fifo->write_index + 1) % 256; // 环形队列
fifo->count++;
return true;
}
这里唯一的难点就是环形的概念
一个 钟表(时钟),指针一直顺时针转,到了 12 点不会变成 13 点,而是重新回到 1 点。
FIFO 的 write_index 就像钟表的指针:如果当前 write_index = 255,下一个写入位置不是 256,而是回到 0(重新开始)。这样就能一直循环存数据,不会超出数组范围。
正常递增
代码语言:javascript代码运行次数:0运行复制write_index = 5;
write_index = (write_index + 1) % 256; // 变成 6
FIFO 快到末尾
代码语言:javascript代码运行次数:0运行复制write_index = 254;
write_index = (write_index + 1) % 256; // 变成 255
FIFO 到达最大索引
代码语言:javascript代码运行次数:0运行复制write_index = 255;
write_index = (write_index + 1) % 256; // 变成 0(回到起点)
这样 FIFO 不会溢出,保证数据始终在 0 ~ 255 之间循环。
检查 FIFO 是否满了(饭盒是否装满了),满了就不能再写入。
写入数据后,写指针 write_index 往前移动,到下一个空位。队伍人数 count++,表示数据增加了。
代码语言:javascript代码运行次数:0运行复制bool fifo_read(FIFO_t *fifo, uint8_t *data) {
if (fifo->count == 0) return false; // 队伍没人,无法取数据
*data = fifo->buffer[fifo->read_index]; // 取出 FIFO 里的数据
fifo->read_index = (fifo->read_index + 1) % 256; // 环形队列
fifo->count--;
return true;
}
如果 FIFO 为空,说明没人排队,无法取数据。
读取 FIFO 里的数据(拿饭),读指针 read_index 往前走。
队伍人数 count--,说明数据减少了。
代码语言:javascript代码运行次数:0运行复制int main() {
FIFO_t fifo;
fifo_init(&fifo);
// 写入数据
fifo_write(&fifo, 10);
fifo_write(&fifo, 20);
fifo_write(&fifo, 30);
// 读取数据
uint8_t value;
while (fifo_read(&fifo, &value)) {
printf("取出的数据: %d\n", value);
}
return 0;
}
FIFO 就像一个排队取饭的过程,先进的先出!
写指针(write_index) 负责存数据,数据存完后指针往前走。
读指针(read_index) 负责取数据,数据取完后指针往前走。
队伍满了(FIFO 满) 就不能再写入,必须先读取。
队伍没人(FIFO 空) 就不能读取,必须先写入数据。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-03-19,如有侵权请联系 cloudcommunity@tencent 删除指针countfifo队列数据