c - 在结构中初始化内联数组 - 如何确保我不会搞砸?
问题描述
有时,出于性能原因,我可能会决定定义一个结构,例如
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
为指针)?
谢谢
解决方案
您的大小计算不正确:结构可能具有嵌入式填充以确保其某些成员的对齐。例如,在 64 位目标上,int
is 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;
}
推荐阅读
- javascript - 对于每个 LOOP,通过 JSON.Stringify 图像的 EXIF 数据
- java - n 个整数扫描器的总和
- javascript - 从映射的卡片中禁用按钮 onClick
- powershell - 从调用 .exe 的 SQL 代理作业捕获错误
- identityserver4 - 如何定义这两个令牌在您的一生中重叠?
- node.js - 如何在url中传递对象数组
- r - 在 R 中,如何为我的系统发育树中的标签着色?(使用来自猿的 BioNj)
- c# - 使用 Newtonsoft 解析 json 字符串会引发 Null 引用执行
- vue.js - vuejs 不会在表单错误时滚动到 div 的顶部
- android - 为什么 dp 中的维度不是预期的?