在C中初始化具有可变长度数组的结构

时间:2021-04-07 22:53:08

Does anyone know if there is a way to initialize a structure containing a variable length array without initializing the array first in a separate variable (and without using malloc)?

有没有人知道是否有办法初始化包含可变长度数组的结构而不首先在单独的变量中初始化数组(并且不使用malloc)?

My structure looks like this:

我的结构看起来像这样:

struct my_struct {
    int *values;
    int size;
}

For now in my code I have that:

现在在我的代码中我有:

void my_function (int size) {
    int values[size];
    struct my_struct mystr = {
        .values = values,
        .size = size
    };
    ...
}

(Array is initialized first, then the structure. This is working but it looks awkward to declare a separate variable for the array.)

(首先初始化数组,然后是结构。这是有效的,但为数组声明一个单独的变量看起来很尴尬。)

This would probably work as well:

这可能也会起作用:

void my_function (int size) {
    struct my_struct mystr = { 
        .values = calloc (size, sizeof (int)),
        .size = size
    };
    ...
}

(but I do not want to use mallocs)

(但我不想使用mallocs)

But what I would like to write is something like:

但我想写的是:

void my_function (int size) {
    struct my_struct mystr = { 
        .values = (int[size]){},
        .size = size
    };
    ...
}

Any idea?

任何想法?

2 个解决方案

#1


3  

First of all, note that you cannot use an array from your stack if you want to return your structure.

首先,请注意,如果要返回结构,则无法使用堆栈中的数组。

int values[size];
struct my_struct mystr = {
    .values = values,
    .size = size
};
return mystr;

This is not going to work since the lifetime of values ends when you return. The same applies if you try to store mystr in a value pointed by a parameter of your function.

这不会起作用,因为返回时值的生命周期结束。如果您尝试将mystr存储在函数参数指向的值中,则同样适用。

Obviously you're not doing that, however I think it's worth to mention anyway.

显然你没有这样做,但我认为无论如何都值得一提。


Answer to your question: it depends on the situation.

回答你的问题:这取决于具体情况。

Can you be sure that size is small? Or else your stack is going to overflow in int values[size]. Is it small and predictable? Stick with your first solution. If it can be large or dependent on user-input, definitely use malloc.

你能确定尺寸小吗?否则你的堆栈将以int值[size]溢出。它是小而可预测的吗?坚持你的第一个解决方案。如果它可能很大或依赖于用户输入,请务必使用malloc。

Are you in some way returning or retaining a persistent pointer to your structure or values? Use malloc (see my first remark).

您是否以某种方式返回或保留指向您的结构或值的持久指针?使用malloc(参见我的第一句话)。

Alternatively, you can also use the struct hack but then you would have to malloc the entire mystr anyway.

或者,您也可以使用struct hack,但是无论如何您都必须使用malloc整个mystr。


One more thing, you wrote:

还有一件事,你写道:

(Array is initialized first, then the structure. This is working but it looks awkward to declare a separate variable for the array.)

(首先初始化数组,然后是结构。这是有效的,但为数组声明一个单独的变量看起来很尴尬。)

I'm not sure what you mean, but the int * is only sizeof(intptr_t), irregardless of the size of the array. So you're not allocating twice the memory for 1 array, if that's what you're thinking.

我不确定你的意思,但int *只是sizeof(intptr_t),不管数组的大小。所以你没有为1个阵列分配两倍的内存,如果这就是你的想法。

#2


-1  

Initializer are unnamed objects initialized by the initializer list. Outside the body of a function, the object has static storage duration. So it is possible to use the address of such an object. With a little help from variadic macros you can try →

初始化程序是由初始化程序列表初始化的未命名对象。在函数体外,对象具有静态存储持续时间。因此可以使用这种对象的地址。在可变参数宏的帮助下,您可以尝试→

 #include <stdio.h>

 struct test {
   int count;
   int *values;
 } test[] = {
 #define init(...) { .count=sizeof( (int[]) {__VA_ARGS__} )/sizeof(int), .values=(int *)&(int []){__VA_ARGS__} }
              init(0,1,2,3,4),
              init(2,4,6,8),
              init(1,3),
              init(42)
            };
 #define test_size ((int) (sizeof test/sizeof *test))

 int main(void)
 {
   for(int array=0; array<test_size; ++array) {
     printf("array %d (%d) : [ ", array+1, test[array].count);
     for(int i=0; i<test[array].count; ++i)
       printf("%d ", test[array].values[i]);
     puts("]");
   }
   return 0;
 }

#1


3  

First of all, note that you cannot use an array from your stack if you want to return your structure.

首先,请注意,如果要返回结构,则无法使用堆栈中的数组。

int values[size];
struct my_struct mystr = {
    .values = values,
    .size = size
};
return mystr;

This is not going to work since the lifetime of values ends when you return. The same applies if you try to store mystr in a value pointed by a parameter of your function.

这不会起作用,因为返回时值的生命周期结束。如果您尝试将mystr存储在函数参数指向的值中,则同样适用。

Obviously you're not doing that, however I think it's worth to mention anyway.

显然你没有这样做,但我认为无论如何都值得一提。


Answer to your question: it depends on the situation.

回答你的问题:这取决于具体情况。

Can you be sure that size is small? Or else your stack is going to overflow in int values[size]. Is it small and predictable? Stick with your first solution. If it can be large or dependent on user-input, definitely use malloc.

你能确定尺寸小吗?否则你的堆栈将以int值[size]溢出。它是小而可预测的吗?坚持你的第一个解决方案。如果它可能很大或依赖于用户输入,请务必使用malloc。

Are you in some way returning or retaining a persistent pointer to your structure or values? Use malloc (see my first remark).

您是否以某种方式返回或保留指向您的结构或值的持久指针?使用malloc(参见我的第一句话)。

Alternatively, you can also use the struct hack but then you would have to malloc the entire mystr anyway.

或者,您也可以使用struct hack,但是无论如何您都必须使用malloc整个mystr。


One more thing, you wrote:

还有一件事,你写道:

(Array is initialized first, then the structure. This is working but it looks awkward to declare a separate variable for the array.)

(首先初始化数组,然后是结构。这是有效的,但为数组声明一个单独的变量看起来很尴尬。)

I'm not sure what you mean, but the int * is only sizeof(intptr_t), irregardless of the size of the array. So you're not allocating twice the memory for 1 array, if that's what you're thinking.

我不确定你的意思,但int *只是sizeof(intptr_t),不管数组的大小。所以你没有为1个阵列分配两倍的内存,如果这就是你的想法。

#2


-1  

Initializer are unnamed objects initialized by the initializer list. Outside the body of a function, the object has static storage duration. So it is possible to use the address of such an object. With a little help from variadic macros you can try →

初始化程序是由初始化程序列表初始化的未命名对象。在函数体外,对象具有静态存储持续时间。因此可以使用这种对象的地址。在可变参数宏的帮助下,您可以尝试→

 #include <stdio.h>

 struct test {
   int count;
   int *values;
 } test[] = {
 #define init(...) { .count=sizeof( (int[]) {__VA_ARGS__} )/sizeof(int), .values=(int *)&(int []){__VA_ARGS__} }
              init(0,1,2,3,4),
              init(2,4,6,8),
              init(1,3),
              init(42)
            };
 #define test_size ((int) (sizeof test/sizeof *test))

 int main(void)
 {
   for(int array=0; array<test_size; ++array) {
     printf("array %d (%d) : [ ", array+1, test[array].count);
     for(int i=0; i<test[array].count; ++i)
       printf("%d ", test[array].values[i]);
     puts("]");
   }
   return 0;
 }