2012-10-14 82 views
4

我有一個結構如何應用結構偏移量?

typedef struct foo { 
    int lengthOfArray1; 
    int lengthOfArray2; 
    int* array1; 
    int* array2; 
} foo; 

我需要爲整個結構和數組的內容分配足夠的內存。因此,假設每個陣列有長度爲5 ...

foo* bar = (foo*)malloc(sizeof(foo) + (sizeof(int) * 5) + (sizeof(int) * 5)); 

我現在有指向數組1和數組2到正確的位置在分配的緩衝區:

bar->array1 = (int*)(&bar->lengthOfArray2 + sizeof(int)); 
bar->array2 = (int*)(bar->array1 + lengthOfArray2); 

這是正確的嗎?

編輯#1

只是爲了澄清任何混淆:我試圖保持內存在一個塊,而不是三個。

編輯#2

我不能使用C99作爲MSVC 2010編譯器不支持它(http://stackoverflow.com/questions/6688895/does-microsoft-visual-studio-2010-supports -c99)。

+0

在一個步驟? NO,是不正確的,只有最後一個成員可以用這種方式分配使用靈活數組(C99),看看http://en.wikipedia.org/wiki/Data_padding –

+0

這可以很好地在一個步。請參閱下面的某些答案。 @DavidRF – alk

+0

我不能使用C99 –

回答

3

繼OP的方法,這應該做的工作:

/* Defining these types allows to change the types without having the need to modify the code. */ 
typedef int Foo_ArrayElement1_t; 
typedef int Foo_ArrayElement2_t; 

typedef struct Foo_s { 
    size_t lengthOfArray1; /* 'size_t' is the type of choice for array/memory dimensions. */ 
    size_t lengthOfArray2; 
    Foo_ArrayElement1_t * array1; 
    Foo_ArrayElement2_t * array2; 
} Foo_t; 

/* 
* Allocates memory to hold a structure of type Foo_t including size for 
* 's1' elements referenced by 'array1' and 's2' elements by 'array2'. 
* The arrays' elements are set to 0. 
* 
* Returns a pointer to the freshly allocated memory or NULL if the memory could not 
* be allocated. 
*/ 
Foo_t * Foo_CreateAndInit(size_t s1, size_t s2) 
{ 
    /* At once allocate all 'Foo_t' (including the memory Foo_t's array pointers shall point to). */ 
    Foo_t * pfoo = calloc(1, 
     sizeof(*pfoo) + 
     s1 * sizeof(*(pfoo->array1) + 
     s2 * sizeof(*(pfoo->array2))); 
    if (pfoo) 
    { 
    pfoo->lengthOfArray1 = s1; 
    pfoo->lengthOfArray2 = s2; 

    /* The first array starts right after foo. */ 
    pfoo->array1 = (Foo_ArrayElement1_t *) (pfoo + 1); 

    /* The second array starts right after s1 elements of where the first array starts. */ 
    pfoo->array2 = (Foo_ArrayElement2_t *) (pfoo->array1 + s1); /* That casting here is not 
     necessaryas long as 'Foo_t.array1' and 'Foo_t.array2' point to the same type but makes 
     the code work even if those types were changed to be different. */ 
    } 

    return pfoo; 
} 

... 

Foo_t * foo = Foo_CreateAndInit(5, 5); 
+0

我擡起頭size_t,它似乎被使用在我不能使用的C99中。 –

+0

從我的知識'size_t'在'C99'之前存在looong。無論如何,數組大小至少不需要「簽名」。所以只要在你的平臺上使用'malloc()'/'calloc()'的參數所使用的類型。 @StormKiernan – alk

+0

你打算:sizeof(* pfoo)?或sizeof(Foo_t)? –

4

您必須分配結構的大小。然後您必須分配具有各自大小的整數數組。

foo* bar = malloc(sizeof(foo)); 

/* somewhere in here the array lengths are set then... */ 

bar->array1 = malloc(sizeof(int) * bar->lengthOfArray1); 
bar->array2 = malloc(sizeof(int) * bar->lengthOfArray2); 
+2

這個答案的關鍵是有兩個步驟,首先分配結構,然後分配結構指向的內存。您不能同時分配結構和數組內存。 –

+0

個人而言,我覺得最好寫一下:bar-> arrayX = malloc(sizeof(* bar-> arrayX)* bar-> lengthOfArrayX);如果您應該決定將類型從int更改爲其他內容。生成相同的代碼。 – Pat

+1

遵循你的方法,你創建了三個獨立的內存區域,這些內存區域可能會使邏輯結構'foo'的處理(複製,清除)包括其動態數組成員更加複雜。 – alk

1

隨着一點點額外的內存(僅適用於C99):

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

typedef struct foo { 
    int lengthOfArray1; 
    int lengthOfArray2; 
    int *array1; 
    int *array2; 
    int array[]; 
} foo; 

int main(void) 
{ 
    foo *bar = malloc(sizeof(foo) + (sizeof(int) * 10)); 

    bar->array1 = &bar->array[0]; 
    bar->array2 = &bar->array[5]; /* 5 or lengthOfArray1 */ 

    return 0; 
} 
+0

你可以通過使用'int array [1]'並且在'malloc'(舊的方法來做一個靈活的數組成員)中減1來完成這項工作。 – nneonneo

+0

@nneonneo,是的,但作爲c-faq說,它不清楚它是合法的或便攜式的http://c-faq.com/struct/structhack.html –

+0

我不能使用C99 –