我正在为环形缓冲区创建一个包含 .h 和 .c 文件的 C 库。理想情况下,您将在主项目中使用类似 ringbuff_init(int buff_size);
的东西初始化这个环形缓冲区库,发送的大小将是缓冲区的大小。当 C 中的数组需要静态初始化时,我该怎么做?
我已经尝试过动态分配数组,但没有成功。肯定可以通过某种方式完成这项任务吗?
我想做的是这样的:
int buffSize[];
int main(void)
{
ringbuffer_init(100); // initialize buffer size to 100
}
void ringbuffer_init(int buff_size)
{
buffSize[buff_size];
}
这显然不能编译,因为数组应该在声明时初始化。所以我的问题真的是,当你为缓冲区之类的东西创建一个库时,你如何在主程序中初始化它(以便在缓冲区库的 .h/.c 文件中)将缓冲区大小设置为想要的尺寸?
您想使用动态内存分配。您最初尝试的直接翻译如下所示:
size_t buffSize;
int * buffer;
int main(void)
{
ringbuffer_init(100); // initialize buffer size to 100
}
void ringbuffer_init(size_t buff_size)
{
buffSize = buff_size;
buffer = malloc(buff_size * sizeof(int));
}
然而,这里的解决方案非常糟糕。让我在这里列出问题:
- 没有检查 malloc 的结果。如果分配失败,它可以返回 NULL。
- 缓冲区大小需要与缓冲区一起存储,否则无法从您的库代码中获知其大小。保留这些全局变量并不是很干净。
- 说起来,这些全局变量绝对不是线程安全的。如果多个线程调用您的库的函数,结果是不可预测的。您可能希望将缓冲区及其大小存储在一个结构中,该结构将从您的 init 函数返回。
- 没有什么能阻止您连续多次调用 init 函数,这意味着每次都会覆盖缓冲区指针,从而导致内存泄漏。
- 必须使用
free
函数最终释放分配的内存。
总而言之,您需要非常仔细地考虑您在库中公开的 API,并且实现虽然不是非常复杂,但也不是微不足道的。
更正确的应该是这样的:
typedef struct {
size_t buffSize;
int * buffer;
} RingBuffer;
int ringbuffer_init(size_t buff_size, RingBuffer * buf)
{
if (buf == NULL)
return 0;
buf.buffSize = buff_size;
buf.buffer = malloc(buff_size * sizeof(int));
return buf.buffer != NULL;
}
void ringbuffer_free(RingBuffer * buf)
{
free(buf.buffer);
}
int main(void)
{
RingBuffer buf;
int ok = ringbuffer_init(100, &buf); // initialize buffer size to 100
// ...
ringbuffer_free(&buf);
}
即使这样也不是没有问题,因为如果为同一个缓冲区多次调用 init 函数,仍然存在潜在的内存泄漏,并且您的库的客户端不能忘记调用 free 函数。
我是一名优秀的程序员,十分优秀!