首页 > 解决方案 > 在结构中初始化内联数组 - 如何确保我不会搞砸?

问题描述

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

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为指针)?

谢谢

标签: cstructmalloc

解决方案


您的大小计算不正确:结构可能具有嵌入式填充以确保其某些成员的对齐。例如,在 64 位目标上,intis 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;
}

推荐阅读