【问题标题】:Is it possible to set the size of an array within structure during runtime?是否可以在运行时设置结构内数组的大小?
【发布时间】:2016-09-07 19:35:05
【问题描述】:

我的结构如下:

struct Query {  
    int     pages[];
    int     currentpage;
};

我想知道是否可以在创建结构后设置这个数组的大小。

Query new = malloc(sizeof(struct Query));

之后,我将执行一些计算,然后告诉我pages[] 需要的大小。如果pages[] 需要大小为 4,我该如何设置?

【问题讨论】:

  • int pages[]; --> int *pages; 然后malloc-吃掉它。请记住,页面必须在整个结构 free 之前为 freeed。
  • 在其他语言中,您可以为结构创建构造函数。不确定c。但我认为这是要走的路。
  • pages 成为一个 int 指针。这样,您可以在创建结构后使用 malloc 在堆中为其分配内存。
  • 这个结构是非法的。灵活数组成员必须是最后一个元素。然后就可以调整大小了。

标签: c arrays struct


【解决方案1】:

在 C99 中你可以使用Flexible array members:

struct Query {  
    int currentpage;
    int pages[]; /* Must be the last member */
};

struct Query *new = malloc(sizeof(struct Query) + sizeof(int) * 4);

【讨论】:

  • OP 说要分配结构并在一些计算之后分配数组。您应该添加一个realloc 示例。顺便说一句,我个人认为,“专家”人员必须使用灵活数组。
  • @LPs,我认为你是对的,但 reallocing 的大小(与第一个 malloc 不同)对我来说似乎很危险,不是吗?对于这种具体情况,我认为 OP 意味着在运行时不知道数组大小的情况下分配结构(只有一个 int 和一个数组在 structint currentPage 可以存储在 @ 之前的临时变量中987654329@,然后重新分配给struct),但我可能是错的。原谅我的英语不好。
  • 我同意。这种特定情况可以按照您的描述工作。我认为realloc 不会比使用malloc 更危险。我的意思是:您必须知道使用灵活数组在做什么。 +1
【解决方案2】:

pages成员的类型改为指针。

struct Query {  
    int *pages;
    int currentpage;
};

struct Query *test = malloc(sizeof(struct Query));

if (test != NULL)
{
   //your calculations

   test->pages = malloc(result_of_your_calcs);
   if (test->pages != NULL)
   {
      // YOUR STUFF
   }
   else
   {
      // ERROR
   }
}
else
{
   // ERROR
}

当你free你的结构时,你必须相反。

free(test->pages);
free(test);

【讨论】:

  • 我想你的意思是if (test->pages == NULL) { /* ERROR */ },如果test->pages != NULL不是错误
【解决方案3】:

您可以使用灵活的数组成员(详见@AlterMann's answer)(C99+)或零长度数组(GNU C)。

引用https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

在 GNU C 中允许使用零长度数组。它们作为结构的最后一个元素非常有用,它实际上是可变长度对象的标头:

struct line {
   int length;
   char contents[0];
};

struct line *thisline = (struct line *)
   malloc (sizeof (struct line) + this_length);
thisline->length = this_length;

对于标准 C90,链接网站提到

在 ISO C90 中,您必须将 contents 的长度设为 1,这意味着要么浪费空间,要么使 malloc 的参数复杂化。

这意味着要使代码在标准 C90/C89 中运行,char contents[0]; 应该是 char contents[1];

【讨论】:

  • GCC 支持灵活的数组成员,因此没有任何理由使用零大小的数组。而且你不需要强制转换 maloc
  • 是的。但是灵活的数组成员仅在 C99+ 中是标准的(是的,我知道 C89 很古老,但值得一提)。至于演员表,我只是从链接网站复制代码(我知道不需要演员表)
  • @M.M:在一些允许它们的实现中,零大小的数组比灵活的数组成员有一些优势。例如,如果程序员注意对齐,给定 struct SIZED_ARRAY {int size; int dat[0];} it would be possible to create an initialized instance via struct { SIZED_ARRAY arr; int dat[4];} my_array = {{4}, {1,2,3,4}};`。虽然一些 C99 编译器提供有用的扩展,但我认为 C99 本身并没有提供任何实用的等价物。
【解决方案4】:

声明为指针,之后使用malloc

struct Query {  
    int * pages;
    int   currentpage;
};

. . .

struct Query obj;
obj.pages = malloc(n * sizeof(int));   // n is the length you want

【讨论】:

    【解决方案5】:

    最好的解决方案是使用指向int 的指针而不是数组。

    你需要改变:

    int pages[];
    

    到:

    int *pages;
    

    然后像这样动态分配它:

    Query *new = malloc(sizeof(struct Query));
    if (new == NULL)
        printf ("Error\n");
    else
    {
        new->pages = malloc(4*sizeof(int));
        if (new->pages == NULL)
           printf ("Error\n");
    }
    

    否则,如果您想保持格式,您将使用 C99 模式。将pages 声明为结构的最后一个成员,如下所示:

    struct Query {  
        int currentpage;
        int pages[];
    };
    

    然后做:

    Query *new = malloc(sizeof(struct Query) + 4*sizeof(int));
    

    【讨论】:

    • 不应该是Query * new = ...吗?
    • @Shreevardhan 是的,我错过了星号!谢谢,我编辑了我的帖子:)
    • new->pages = malloc(4*sizeof(int)); 如果之前的malloc for new 失败,将导致分段错误。
    猜你喜欢
    • 2017-08-30
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多