2011-02-13 112 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功能。