初始化结构中的内联数组-如何确保我不会弄乱它?

时间:2019-07-18 18:53:40

标签: c struct malloc

有时候出于性能原因,我可能会决定定义一个结构,例如

typedef struct {
    size_t capacity;
    size_t size;
    int offset;
    void* data[];
} ring_buffer;

在结构本身中内联data。我目前正在将创建函数定义为

ring_buffer* ring_buffer_create(size_t capacity) {
    int struct_size = 
      sizeof(int) + 2 * sizeof(size_t) + 
      capacity * sizeof(void*);
    ring_buffer* rb = (ring_buffer*)malloc(struct_size);
    rb->capacity = capacity;
    rb->offset = 0;
    rb->size = 0;
    return rb;
}

只要C编译器不做一些奇怪的字段填充/对齐,它(如果我没有计算错的话)就可以正常工作。

人们通常如何处理这种情况(当然,除了将data定义为指针之外)?

谢谢

1 个答案:

答案 0 :(得分:2)

您的尺寸计算不正确:该结构可能具有嵌入式填充物,以确保其某些成员对齐。例如,在64位目标上,int是4字节,后面的void *data[]数组需要8字节对齐,因此编译器将在data成员之前插入4字节的填充。

大小应通过以下方式计算:

size_t struct_size = sizeof(ring_buffer) + capacity * sizeof(void *);

或者可能:

size_t struct_size = offsetof(ring_buffer, data) + capacity * sizeof(void *);

请注意,size的类型应为size_t,并且您应该测试malloc的失败,以避免未定义的行为:

ring_buffer *ring_buffer_create(size_t capacity) {
    size_t struct_size = sizeof(ring_buffer) + capacity * sizeof(void *);
    ring_buffer *rb = malloc(struct_size);
    if (rb) {
        rb->capacity = capacity;
        rb->offset = 0;
        rb->size = 0;
    }
    return rb;
}