它部分取决于元素类型。您当然可以使用字符串来做到这一点;对于其他一些类型,您必须担心对齐和填充问题。
struct data_channel
{
char *chan_name;
char *chan_type;
char *chan_units;
};
struct data_channel *chan;
size_t name_size = 9;
size_t type_size = 10;
size_t unit_size = 5;
chan = malloc(sizeof(struct data_channel) + name_size + type_size + unit_size);
if (chan != 0)
{
chan->chan_name = (char *)chan + sizeof(*chan);
chan->chan_type = chan->chan_name + name_size;
chan->chan_units = chan->chan_type + type_size;
}
这在实践中可以正常工作——在标准标准化之前已经进行了很长时间。我不能立即明白为什么标准会不允许这样做。
更棘手的是,如果您需要分配一个数组int
,比如说,以及两个字符串。然后你必须担心对齐问题。
struct data_info
{
char *info_name;
int *info_freq;
char *info_unit;
};
size_t name_size = 9;
size_t freq_size = 10;
size_t unit_size = 5;
size_t nbytes = sizeof(struct data_info) + name_size + freq_size * sizeof(int) + unit_size;
struct data_info *info = malloc(nbytes);
if (info != 0)
{
info->info_freq = (int *)((char *)info + sizeof(*info));
info->info_name = (char *)info->info_freq + freq_size * sizeof(int);
info->info_unit = info->info_name + name_size;
}
这采用了简单的权宜之计,int
首先分配最严格对齐的类型( 的数组),然后再分配字符串。但是,这部分是您必须对可移植性做出判断的地方。我相信代码在实践中是可移植的。
C11 具有可以改变这个答案的对齐工具(_Alignof
and_Alignas
和<stdalign.h>
,加上max_align_t
in <stddef.h>
)(但我没有充分研究它们,所以我不确定如何),但这里概述的技术将适用于任何版本的 C 提供你小心数据的对齐。
请注意,如果结构中只有一个数组,则 C99 提供了一种替代旧的“结构黑客”的方法,称为灵活数组成员(FAM)。这允许您明确地将数组作为结构的最后一个元素。
struct data_info
{
char *info_name;
char *info_units;
int info_freq[];
};
size_t name_size = 9;
size_t freq_size = 10;
size_t unit_size = 5;
size_t nbytes = sizeof(struct data_info) + name_size + freq_size * sizeof(int) + unit_size;
struct data_info *info = malloc(nbytes);
if (info != 0)
{
info->info_name = ((char *)info + sizeof(*info) + freq_size * sizeof(int));
info->info_units = info->info_name + name_size;
}
info_freq
请注意,在此示例中,没有初始化 FAM 的步骤。你不能有多个这样的数组。
请注意,概述的技术不能轻易应用于结构数组(至少,外部结构的数组)。如果你付出相当大的努力,你可以让它发挥作用。另外,请注意realloc()
; 如果重新分配空间,如果数据已移动,则必须修复指针。
另一点:特别是在 64 位机器上,如果字符串的大小足够统一,您可能会更好地在结构中分配数组,而不是使用指针。
struct data_channel
{
char chan_name[16];
char chan_type[16];
char chan_units[8];
};
这占用 40 个字节。在 64 位机器上,原始数据结构将占用 24 个字节用于三个指针,另外 24 个字节用于(9 + 10 + 5)字节数据,总共分配了 48 个字节。