具有不同大小结构的struct数组的malloc()

如果每个struct包含一个大小不一的字符串数组,那么malloc如何正确地构造一个结构数组?

因此,每个结构可能具有不同的大小,并且无法实现

realloc(numberOfStructs * sizeof(structName))

malloc(initialSize * sizeof(structName)

如何为此分配内存并跟踪发生的情况?

我根据您提供的信息在这里做了一些猜测。 我可以看到想要重新分配结构数组的唯一原因是,如果要向该数组添加更多结构。 这很酷。 想要这种动态存储有很多理由。 处理它的最好方法,特别是如果结构本身是动态的,就是保留一些指向这些结构的指针 。 例:

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

如果你的结构有一个char *,它占用一个指针的大小。 如果它有char [200],则需要200个字节。

一般来说,你没有。 您可能想要执行此操作有两个原因:

  1. 这样一个free()就会释放整个内存块。
  2. 避免内部内存碎片。

但除非你有特殊情况,否则两者都不是很引人注目,因为这种方法存在严重缺陷:

如果你这样做,那么block[i]是没有意义的。 您尚未分配数组。 如果没有检查结构或者在块中有关于结构的大小/位置的外部信息,就无法确定下一个结构的起始位置。

你的struct类型是如何声明的还不是很清楚。 C99有一个特殊的构造用于这样的东西,称为struct灵活数组成员:

作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型; 这称为灵活的arrays成员。

你可以做点什么

 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; 

为了更舒适地使用它,你可能最好将它包装成宏或内联函数。