首页 文章

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

提问于
浏览
1

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

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

realloc(numberOfStructs * sizeof(structName))

malloc(initialSize * sizeof(structName)

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

4 回答

  • 3

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

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

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

  • 4

    一般来说,你没有 . 您可能希望这样做有两个原因:

    • 因此单个 free() 将释放整个内存块 .

    • 避免内部内存碎片 .

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

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

  • 1

    您的 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;
    

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

相关问题