我正在使用一个具有一个带结构数组的函数的库。该结构和函数具有以下布局:
struct TwoInt32s
{
int32_t a;
int32_t b;
};
void write(struct TwoInt32s *buffer, int len);
我的初步测试表明,这样的结构数组与int32_t
的数组具有相同的内存布局,所以我可以这样做:
int32_t *buffer = malloc(2 * len * sizeof(int32_t));
/* fill in the buffer */
write((struct TwoInt32s*)buffer, len);
但是我想知道这是否普遍存在。使用int32_t
数组大大简化了我的代码。
根据我的阅读,C保证了一些关于struct padding的东西:
由此我可以推断a
和b
之间没有填充。但是结构可能最后会有填充。我对此表示怀疑,因为它在32位和64位系统上都是字对齐的。有没有人有这方面的其他信息?
答案 0 :(得分:10)
实现可以自由填充结构 - a
和b
之间可能有未使用的字节。保证第一个成员不会从结构的开头偏移。
通常,您使用特定于编译器的编译指示来管理此类布局,例如:
#pragma pack(push)
#pragma pack(1)
struct TwoInt32s
{
int32_t a;
int32_t b;
};
#pragma pack(pop)
答案 1 :(得分:3)
malloc分配字节。你为什么选择“2 * len”?
你可以简单地使用“sizeof”:
int32_t *buffer = malloc(len * sizeof(TwoInt32s));
/* fill in the buffer */
write((struct TwoInt32s*)buffer, len);
正如Erik所说,打包结构是一个好习惯。
答案 2 :(得分:2)
最不安全,但转换 - 即创建一个新数组并用结构中找到的值填充它,然后终止结构。
答案 3 :(得分:0)
您可以分配结构,但将其成员视为一种虚拟数组:
struct TwoInt32s *buffer = malloc(len * sizeof *buffer);
#define BUFFER(i) (*((i)%2 ? &buffer[(i)/2].b : &buffer[(i)/2].a))
/* fill in the buffer, e.g. */
for (int i = 0; i < len * 2; i++)
BUFFER(i) = i;
不幸的是,GCC和Clang目前都没有“获得”此代码。