C中结构中的运行时条件字段

C中结构中的运行时条件字段,c,memory-management,struct,runtime,conditional,C,Memory Management,Struct,Runtime,Conditional,我有一个用C编写的特定应用程序,它需要高效的内存。它正在收集统计数据,因此我需要能够在运行时“打开/关闭”某些字段,以最大限度地减少内存消耗。 我知道您可以使用宏定义条件结构字段,但如果我没有弄错的话,那是编译时,有没有可能在运行时在C中这样做 例如: 输入: collect (A,B) 将产生如下结构: struct statistics{ double A; double B; }; 但是输入: collect (A,B,C) 将产生如下结构: struct statistics{ d

我有一个用C编写的特定应用程序,它需要高效的内存。它正在收集统计数据,因此我需要能够在运行时“打开/关闭”某些字段,以最大限度地减少内存消耗。 我知道您可以使用宏定义条件结构字段,但如果我没有弄错的话,那是编译时,有没有可能在运行时在C中这样做

例如:

输入:

collect (A,B)
将产生如下结构:

struct statistics{
double A;
double B;
};
但是输入:

collect (A,B,C)
将产生如下结构:

struct statistics{
double A;
double B;
double C;
};

在运行时关闭结构中的某些字段是不可能的。但是,您可以有一个指针,指向可以表示多个字段的动态分配的双精度数组。 例如:

#include <stdio.h>
#include <stdlib.h>

struct stats
{
    size_t number_of_doubles;
    double* data;
};

void make_stats(struct stats* pStats)
{
    pStats->number_of_doubles = 3;
    pStats->data = (double*) malloc(pStats->number_of_doubles * sizeof(double));
}

void delete_stats(struct stats* pStats)
{
    free(pStats->data);
}

int main()
{
    struct stats foo;

    make_stats(&foo);

    foo.data[0] = 3.0;
    foo.data[1] = 5.0;
    foo.data[2] = 7.0;

    delete_stats(&foo);    
    return 0;
}
#包括
#包括
结构统计
{
双倍的大小和数量;
双*数据;
};
void make_stats(结构统计*pStats)
{
pStats->双倍数量=3;
pStats->data=(双精度*)malloc(pStats->双精度数量*sizeof(双精度));
}
void delete_stats(结构统计*pStats)
{
免费(pStats->数据);
}
int main()
{
struct stats foo;
制作_统计数据(&foo);
foo.data[0]=3.0;
foo.data[1]=5.0;
foo.data[2]=7.0;
删除_统计数据(&foo);
返回0;
}

代替通常的结构数组(AoS):

您可以切换到阵列结构(SoA):


无法在运行时更改结构的大小。每当您在堆栈或堆上分配可执行指令时,结构的大小就会内置到可执行指令中。另一个例子是,结构的sizeof在编译时可用,因此不能在运行时更改


当然,您可以使用带有自定义内存管理器的自定义结构来实现这一点,但它不是直接内置在语言中的。

您需要使用某种动态分配和结构。在这种情况下,最好为每个记录使用动态大小的数组,而不是结构(假设所有字段都是相同的类型,即,
double
?)。或者,您可以从AoS切换到SoA,其中每个数组都是指针,仅在需要时分配。对,(它们不都是double,大部分是double和integer);然而,指针本身是4字节的,所以我将有一个指针,而不是所有这些字段中的每一个,它可能会被分配,也可能不会被分配——但在内存中的顺序仍然相同。有可能做得更好吗?我已经将上面的后一个建议充实到下面更完整的答案中了……谢谢!我想这会起作用,我需要更改对于某些统计数据的存在或不存在,数字会加倍到某种标志上——但我想这是可行的。不客气。我已经添加了一个主数据供您尝试并删除。如果这对您有帮助,请标记为回答:)谢谢您的演示,先生!考虑到收集的统计数据数量超过100,这将仍然至少有一个4bytes*100大小的结构。当然-我不知道您正在收集多少数据以及内存限制是什么,因此给出最佳解决方案并不容易。如果内存真的很紧,那么就使用动态大小的数组-这会稍微减少开销,但代价是更复杂地访问单个元素。@user2662165:PS:您知道在AoS的情况下只有上述结构的一个实例吗?是的,事实上,如果不是在以下情况下,它将非常有用:我仍然需要维护一个结构数组,因为每个实例都有不同的字段,基于它需要收集的内容——因此,一个实例将收集A和B,而另一个实例收集A、B和C。因此,如果我将其实现为SOA,它将变得更加复杂。现在,如果我使用上面的AoS,并为每个实例分配一个标志,以显示它正在收集什么,我将知道结构中的数据数组有多大,以及每个字段所属的位置等等。。。
struct statistics{
    double A;
    double B;
    double C;
};

struct statistics my_statistics = malloc(1000000 * sizeof(my_statistics[0]));

my_statistics[0].A = 1;
my_statistics[0].B = 2;
my_statistics[0].C = 3;
struct statistics{
    double *A;
    double *B;
    double *C;
};

struct statistics my_statistics;

my_statistics.A = using_A ? malloc(1000000 * sizeof(my_statistics.A[0])) : NULL;
my_statistics.B = using_B ? malloc(1000000 * sizeof(my_statistics.B[0])) : NULL;
my_statistics.C = using_C ? malloc(1000000 * sizeof(my_statistics.C[0])) : NULL;

my_statistics.A[0] = 1;
my_statistics.B[0] = 2;
my_statistics.C[0] = 3;