使用malloc是否会导致;“可选”;结构域?

使用malloc是否会导致;“可选”;结构域?,c,struct,malloc,optional,heap-memory,C,Struct,Malloc,Optional,Heap Memory,我正在实现一个结构,其中我需要(在运行时)有一个可选字段。 所以我想: /。。。 #包括 结构测试{ int x;//必须是 int y;//可选(必须是最后一个字段..(?) }; int main(int argc,字符**argv){ //使用可选字段 结构测试*a=malloc(sizeof(*a)); a->x=11; a->y=55; //没有可选字段 结构测试*b=malloc(sizeof(*b)-sizeof(int)); b->x=22; // ... 免费(a); 免费(b

我正在实现一个结构,其中我需要(在运行时)有一个可选字段。
所以我想:

/。。。
#包括
结构测试{
int x;//必须是
int y;//可选(必须是最后一个字段..(?)
};
int main(int argc,字符**argv){
//使用可选字段
结构测试*a=malloc(sizeof(*a));
a->x=11;
a->y=55;
//没有可选字段
结构测试*b=malloc(sizeof(*b)-sizeof(int));
b->x=22;
// ...
免费(a);
免费(b);
返回0;
}
这段代码能满足我的要求吗?
可能会添加一个位字段来检查是否存在可选字段

此外,如果建议的解决方案有效,如果针对多个项目(>100000)的列表实施,那么这样做是否会更好地节省内存

这个代码能满足我的要求吗

嗯,它可以,但你不能依赖它。不要这样做;这不是一种编写正确程序的方法

当你写
b->x=22时b
上进行一次完整的
struct测试一样进行操作。您可能会想,“我只是在为成员
x
的字节中放入22个”,但编译器可能会使用“存储8个字节”指令:

  • 考虑一些将内存组织为8字节组的体系结构。总线只能读写整个8字节块
  • 由于无法在硬件中写入四个字节,因此将四个字节写入内存需要读取八个字节,在处理器寄存器中对它们进行操作以在其中四个字节中插入所需的值,然后将八个字节写入内存
  • 编译器想要优化
    b->x=22,它知道
    y
    尚未设置,因此允许有任何值。因此,编译器不使用低效的写入四字节序列,而是生成一个八字节存储,将22放入
    b->x
    ,0放入
    b->y
然后,这将失败,因为编译器刚刚将0写入内存,该内存可能正在用于其他用途,因为它不是为
b
分配的空间的一部分

“如果你对编译器撒谎,它会报仇的。”-亨利·斯宾塞

这个代码能满足我的要求吗

嗯,它可以,但你不能依赖它。不要这样做;这不是一种编写正确程序的方法

当你写
b->x=22时b
上进行一次完整的
struct测试一样进行操作。您可能会想,“我只是在为成员
x
的字节中放入22个”,但编译器可能会使用“存储8个字节”指令:

  • 考虑一些将内存组织为8字节组的体系结构。总线只能读写整个8字节块
  • 由于无法在硬件中写入四个字节,因此将四个字节写入内存需要读取八个字节,在处理器寄存器中对它们进行操作以在其中四个字节中插入所需的值,然后将八个字节写入内存
  • 编译器想要优化
    b->x=22,它知道
    y
    尚未设置,因此允许有任何值。因此,编译器不使用低效的写入四字节序列,而是生成一个八字节存储,将22放入
    b->x
    ,0放入
    b->y
然后,这将失败,因为编译器刚刚将0写入内存,该内存可能正在用于其他用途,因为它不是为
b
分配的空间的一部分


“如果你对编译器撒谎,它会报复的。”-亨利·斯宾塞我认为你提出的解决方案是危险的。使用两种不同的结构:

struct test_x {
   int x;
};

struct test_xy {
  int x;
  int y;
};
要么有两个数组,要么将一个void*与鉴别器(例如标记指针)一起存储到其中一个。另一个选项是为可选元素使用指针,但sizeof(int*)至少在我的框中与sizeof(int)相同,因此这只会使事情变得更大

如果所有y成员都是可选的,请考虑列布局,或者您可以对数据进行排序,使所有xy元素都排在第一位:

struct test_column {
  int *x;
  int *y;
};

struct test_column t = {
  .x = malloc(100000 * sizeof(int)),
  .y = 0
在这种情况下,它对您没有帮助,但联合是两个结构共享内存的标准方式,因此每个元素的大小都是相同的 max(sizeof(test_xy)、sizeof(test_x))而不是sizeof(test_xy)+sizeof(test_x)


最后,考虑压缩,特别是如果你使用Test-Bar列格式。

< P>我认为你提出的解决方案是危险的。使用两种不同的结构:

struct test_x {
   int x;
};

struct test_xy {
  int x;
  int y;
};
要么有两个数组,要么将一个void*与鉴别器(例如标记指针)一起存储到其中一个。另一个选项是为可选元素使用指针,但sizeof(int*)至少在我的框中与sizeof(int)相同,因此这只会使事情变得更大

如果所有y成员都是可选的,请考虑列布局,或者您可以对数据进行排序,使所有xy元素都排在第一位:

struct test_column {
  int *x;
  int *y;
};

struct test_column t = {
  .x = malloc(100000 * sizeof(int)),
  .y = 0
在这种情况下,它对您没有帮助,但联合是两个结构共享内存的标准方式,因此每个元素的大小都是相同的 max(sizeof(test_xy)、sizeof(test_x))而不是sizeof(test_xy)+sizeof(test_x)


最后,考虑压缩,特别是如果你使用Test-Bar列格式。

你所尝试的不符合C标准,因为你试图使用一个类型为StultTest< /Cord>的对象,它没有足够的内存分配,即使你只访问内存分配的字段。它可能有用,但你不能依赖它

您可以使用灵活的数组成员:

struct test {
  int x;
  int y[];
};
在这样的结构中,
sizeof(struct test)
不包括最后一个成员。可以通过为结构分配空间加上最后一个成员所需的数组元素来使用这样的结构。例如:

struct test *b = malloc(sizeof(*b) + sizeof(int));
b->x = 1;
b->y[0] = 2;
Y