struct中的动态数组大小没有其他成员表示大小

时间:2017-03-03 04:42:07

标签: c design-patterns

我有一个结构定义为:

struct Voxel1
{
   float array[16];
};

以后我可以将图像分配为指定数量的体素的连续存储器,例如,

int voxelNum = 1000;
Voxel1* image = (Voxel1*)calloc(voxelNum, sizeof(Voxel1));

然后我可以访问sizeof(Voxel1)的连续内存来执行某些操作,例如,

Voxel1 a;
//do some computation on a, 
//copy it to the 101-th voxel in the image
image[100] = a;

我的问题是后来我决定在运行时确定数组的大小,即Voxel1中的数组成员是动态大小。有没有办法可以做到?我的要求是我不想保存额外的成员来指示数组的大小,如下所示:

struct Voxel2
{
   size_t size;
   float* array;
}IDontWantThisDefinition;

由于这个额外的成员,后来我的实际体素2大小将是sizeof(float)*size+sizeof(size_t),现在当我尝试修改体素值时,它们不像以前那样连续。

我想要的是一些定义(我知道Voxel3无效)具有以下定义,除了size可以在运行时决定:

struct Voxel3
{
   //so I want size to be static so that it does not take memory on the stack
   //also I want it to be const so that it can be used to define array's size
   static const size_t size;
   float array[size];
}DesireButInvalidDefinition;

在程序中我可以做这样的事情:

int main(int argc, char** argv)
{
    int arraysize = 32;
    //allocate 1000 voxels where each voxel has 32 float element
    Voxel3* image = (Voxel3*)calloc(1000, sizeof(Voxel3));
    Voxel3 anotherVoxel;
    image[100]=anotherVoxel;
}

我不确定是否有任何解决方案可以满足这样的设计,或者哪种设计可以做到接近我想要的东西。提前谢谢。

2 个答案:

答案 0 :(得分:1)

很难说最好的方法是什么,但正如我在最高评论中提到的那样,将大小移到结构定义之外。

首先,你必须在做任何事情之前计算动态尺寸。

int voxel_size;                         // dynamically computed

typedef struct _Voxel {
    float *array;                       // count is voxel_size
} Voxel;

typedef struct _VoxelArray {
    int count;
    Voxel *voxels;
} VoxelArray;

void
voxel_init(Voxel *vox)
{

    vox->array = calloc(voxel_size,sizeof(float));
}

Voxel *
voxel_alloc(int count)
{
    Voxel *vox;

    vox = calloc(count,sizeof(voxel));

    for (int idx = 0;  idx < count;  ++idx)
        voxel_init(vox + idx);

    return vox;
}

VoxelArray *
voxel_array(VoxelArray *arr,int count)
{

    if (arr == NULL)
        arr = calloc(1,sizeof(VoxelArray));

    arr->count = count;
    arr->voxels = voxel_alloc(count);

    return arr;
}

int
main(int argc, char** argv)
{

    voxel_size = 32;

    Voxel anotherVoxel;
    voxel_init(&anotherVoxel);

    //allocate 1000 voxels where each voxel has 32 float element
    Voxel *image = voxel_alloc(1000);
    image[100] = anotherVoxel;

    VoxelArray varray;
    voxel_array(&varray,1000);
    varray.voxels[100] = anotherVoxel;

    VoxelArray *varrptr = voxel_array(NULL,1000);
    varrptr->voxels[100] = anotherVoxel;

    return 0;
}

答案 1 :(得分:-2)

通过分离数据和数据访问器,这就是我得到的。但不是内存管理的一个很好的例子。

#include <cstddef>
#include <cstdlib>

// Both Voxel3 and Voxel3Image are just data accessors,
// which provide a way to access the real data.

struct Voxel3
{
    static size_t size;
    float *array;
    Voxel3(float *data = nullptr) {
        array = data;
    }
    // 'image[100]=anotherVoxel;' won't do the right
    // thing(deep copy) without this.
    Voxel3 & operator = (const Voxel3 &v) {
        for (size_t i = 0; i < size; ++i)
            array[i] = v.array[i];
        return *this;
    }
};

size_t Voxel3::size;

// you want image[100], use this.
struct Voxel3Image
{
    float *data_ref;
    Voxel3Image(float *data = nullptr) {
        data_ref = data;
    }
    // image[100] need this.
    Voxel3 operator [] (int i) {
        return Voxel3(data_ref + i * Voxel3::size);
    }
};

int main(int argc, char** argv)
{
    Voxel3::size = 32;

    float *real_data = (float*)calloc(1000,
                                      sizeof(float) * Voxel3::size);
                                      // sizeof(Voxel3) == sizeof(float *),
                                      // not what your want.

    // allocate 1000 voxels where each voxel has 32 float element
    Voxel3Image image( real_data );
    Voxel3 anotherVoxel;
    // initialize anotherVoxel
    image[100]=anotherVoxel;
    return 0;
}