2011-02-13 146 views
1

如果每個結構體包含大小不同的字符串數組,則malloc如何正確地構造一個結構體數組?具有不同大小的結構數組的malloc()結構

因此,每個結構可能有不同的大小,將使它不可能

的realloc(numberOfStructs *的sizeof(structName))

的malloc(INITIALSIZE * sizeof(structName)

如何爲此分配內存並跟蹤發生了什麼?

+2

每個結構的大小是固定的。如果你的結構中有一個可以溢出其大小的數組,那麼這是另一回事,但編譯器不關心。 – Mehrdad 2011-02-13 03:56:14

+0

另一個故事是我的問題和疑問:) – jarryd 2011-02-13 03:59:12

+1

你的結構是什麼樣子的? – jswolf19 2011-02-13 03:59:44

回答

3

我在這裏根據您提供的信息進行猜測。我可以看到想要構造一個數組的realloc的唯一原因是如果你想向該數組添加更多的結構。這很酷。有很多理由需要這種動態存儲。處理它的最好方法,特別是如果結構本身是動態的,就是將指針保存到這些結構中。例如:

1.數據結構:

typedef struct { 
    int numberOfStrings; 
    char ** strings; 
} 
stringHolder; 

typedef struct { 
    int numberOfStructs; 
    stringHolder ** structs; 
} 
structList; 

2.管理字符串動態數組:

void createNewStringHolder(stringHolder ** holder) { 
    (*holder) = malloc(sizeof(stringHolder)); 
    (*holder)->numberOfStrings = 0; 
    (*holder)->strings = NULL; 
} 

void destroyStringHolder(stringHolder ** holder) { 
    // first, free each individual string 
    int stringIndex; 
    for (stringIndex = 0; stringIndex < (*holder)->numberOfStrings; stringIndex++) 
    { free((*holder)->strings[stringIndex]); } 
    // next, free the strings[] array 
    free((*holder)->strings); 
    // finally, free the holder itself 
    free((*holder)); 
} 

void addStringToHolder(stringHolder * holder, const char * string) { 
    int newStringCount = holder->numberOfStrings + 1; 
    char ** newStrings = realloc(holder->strings, newStringCount * sizeof(char *)); 
    if (newStrings != NULL) { 
     holder->numberOfStrings = newStringCount; 
     holder->strings = newStrings; 
     newStrings[newStringCount - 1] = malloc((strlen(string) + 1) * sizeof(char)); 
     strcpy(newStrings[newStringCount - 1], string); 
    } 
} 

3.管理結構的動態數組:

void createNewStructList(structList ** list, int initialSize) { 
    // create a new list 
    (*list) = malloc(sizeof(structList)); 
    // create a new list of struct pointers 
    (*list)->numberOfStructs = initialSize; 
    (*list)->structs = malloc(initialSize * sizeof(stringHolder *)); 
    // initialize new structs 
    int structIndex; 
    for (structIndex = 0; structIndex < initialSize; structIndex++) 
    { createNewStringHolder(&((*list)->structs[structIndex])); } 
} 

void destroyStructList(structList ** list) { 
    // destroy each struct in the list 
    int structIndex; 
    for (structIndex = 0; structIndex < (*list)->numberOfStructs; structIndex++) 
    { destroyStringHolder(&((*list)->structs[structIndex])); } 
    // destroy the list itself 
    free((*list)); 
} 

stringHolder * addNewStructToList(structList * list) { 
    int newStructCount = list->numberOfStructs + 1; 
    size_t newSize = newStructCount * sizeof(stringHolder *); 
    stringHolder ** newList = realloc(list->structs, newSize); 
    if (newList != NULL) { 
     list->numberOfStructs = newStructCount; 
     list->structs = newList; 
     createNewStringHolder(&(newList[newStructCount - 1])); 
     return newList[newStructCount - 1]; 
    } 
    return NULL; 
} 

4。主程序:

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

int main (int argc, char * argv[]) { 
    structList * allHolders; 
    createNewStructList(&allHolders, 10); 

    addStringToHolder(allHolders->structs[4], "The wind took it"); 
    addStringToHolder(allHolders->structs[4], "Am I not merciful?"); 
    addStringToHolder(allHolders->structs[7], "Aziz, Light!"); 

    printf("%s\n", allHolders->structs[4]->strings[0]); // The wind took it 
    printf("%s\n", allHolders->structs[4]->strings[1]); // Am I not merciful? 
    printf("%s\n", allHolders->structs[7]->strings[0]); // Aziz, Light! 

    stringHolder * newHolder = addNewStructToList(allHolders); 
    addStringToHolder(newHolder, "You shall not pass!"); 
    printf("%s\n", newHolder->strings[0]);    // You shall not pass! 
    printf("%s\n", allHolders->structs[10]->strings[0]); // You shall not pass! 

    destroyStructList(&allHolders); 
    return 0; 
} 
4

如果你的結構有一個char *,它將佔用一個指針的大小。如果它有一個字符[200],則佔用兩百個字節。

1

您一般不會。有兩個原因你可能想要做到這一點:

  1. 這樣一個單一的free()將釋放整個內存塊。
  2. 避免內部內存碎片。

但是,除非你有一個特殊的情況,也不是非常引人注目的,因爲沉重的缺點,這種方法:

如果你這樣做,那麼block[i]是沒有意義的。你還沒有分配數組。沒有辦法確定你的下一個結構是從哪裏開始的,沒有檢查結構,也沒有關於塊中結構的大小/位置的外部信息。

0

它不是那麼清楚你struct類型的聲明方式。 C99具有這樣的事情一個特殊的構建體,被稱爲struct的柔性陣列成員:

作爲一個特殊的情況下,與一個以上的命名 構件的結構可以具有一個不完整的陣列 類型的 的最後一個元素;這被稱爲靈活數組 成員。

你可以做類似

typedef struct myString myString; 
struct myString { size_t len; char c[]; }; 

然後,您可以用

size_t x = 35; 
myString* s = malloc(sizeof(myString) + x); 
s->len = x; 

分配這樣的野獸,用

size_t y = 350; 
{ 
    myString* tmp = realloc(s, sizeof(myString) + y); 
    if (!tmp) abort(); // or whatever 
    tmp->len = y; 
} 
s = tmp; 

重新分配它爲了舒適地使用這個你越'd可能會更好地將其包含到宏或inli中ne功能。