2017-03-03 35 views
2

我有一個結構定義爲:動態數組大小而不另一個構件指示大小

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; 

由於這種額外的成員,後來我的實際voxel2規模將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; 
} 

我不知道是否有任何解決方案來滿足這樣的設計,或者什麼設計可以做到接近我想要的東西。提前致謝。

+1

你使用'c'還是'C++'?在你的用例中,它可以有所作爲。對於'c','Voxel2'看起來是最好的選擇。使'size'成爲一個全局/靜態的,定義_outside_ struct –

+0

我將刪除C++標記,因爲它似乎是用C編碼的。 – juanchopanza

回答

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; 
} 
-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; 
}