在结构体内声明整型数组

21
在C语言中,我定义了如下的struct结构体,并希望进行内联初始化。在初始化后,结构体内部的字段和数组foos都不会再改变。第一个代码块的代码可以正常工作。
struct Foo {
  int bar;
  int *some_array;
};

typedef struct Foo Foo;

int tmp[] = {11, 22, 33};
struct Foo foos[] = { {123, tmp} };

然而,我并不需要 tmp 字段。实际上,它只会让我的代码变得杂乱无章(这个例子有点简化了)。因此,我想在声明 foos 的同时声明 some_array 的值。但是我无法找到正确的语法。也许应该以不同的方式定义 some_array 字段?

int tmp[] = {11, 22, 33};
struct Foo foos[] = {
  {123, tmp},                    // works
  {222, {11, 22, 33}},           // doesn't compile
  {222, new int[]{11, 22, 33}},  // doesn't compile
  {222, (int*){11, 22, 33}},     // doesn't compile
  {222, (int[]){11, 22, 33}},    // compiles, wrong values in array
};

1
你必须使用malloc或calloc函数为*some_array分配内存空间。 - Mihai8
3个回答

32

首先,有两种方法:

  • 你知道数组的大小
  • 你不知道那个大小。

在第一种情况下,这是一个静态编程问题,而且并不复杂:

#define Array_Size 3

struct Foo {
    int bar;
    int some_array[Array_Size];
};

您可以使用以下语法来填充数组:

struct Foo foo;
foo.some_array[0] = 12;
foo.some_array[1] = 23;
foo.some_array[2] = 46;

当你不知道数组的大小时,这是一个动态规划问题。你必须询问大小。

struct Foo {

   int bar;
   int array_size;
   int* some_array;
};


struct Foo foo;
printf("What's the array's size? ");
scanf("%d", &foo.array_size);
//then you have to allocate memory for that, using <stdlib.h>

foo.some_array = (int*)malloc(sizeof(int) * foo.array_size);
//now you can fill the array with the same syntax as before.
//when you no longer need to use the array you have to free the 
//allocated memory block.

free( foo.some_array );
foo.some_array = 0;     //optional

其次,typedef 很有用,所以当你写下这样的代码:

typedef struct Foo {
   ...
} Foo;

这意味着您将“struct Foo”一词替换为“Foo”。

因此,语法将如下所示:

Foo foo;   //instead of "struct Foo foo;

干杯。


动态数组在GCC文档的一个扩展中被描述得非常好:长度为零的数组。您可以将长度为零的数组声明为结构体的最后一个成员,并将结构体放置在实际数组内容之前的内存中。请注意,这只是一种扩展方式,标准方法也在那里描述了如何实现相同的功能。 - Palec

17
int *some_array;

在这里,some_array实际上是一个指针,而不是数组。你可以这样定义:

struct Foo {
  int bar;
  int some_array[3];
};

还有一件事,typedef struct Foo Foo; 的整个意义在于使用 Foo 代替 struct Foo。你可以像这样使用 typedef:

typedef struct Foo {
  int bar;
  int some_array[3];
} Foo;

1
另外,你提到“结构体内部的字段和数组foos在初始化后不会改变”,那么你可以在它们的定义前面加上“const”前缀。例如const int some_array[3];。这将允许赋值但不允许修改。 - kfsone
1
@kfsone 您的意思是它将允许初始化,但不允许赋值或修改。 - M.M

2

我将为以下代码段提供答案:

int tmp[] = {11, 22, 33};
struct Foo foos[] = {
  {123, tmp},   // works
  {222, {11, 22, 33}},  // doesn't compile
  {222, new int[]{11, 22, 33}},  // doesn't compile
  {222, (int*){11, 22, 33}},  // doesn't compile
  {222, (int[]){11, 22, 33}},  // compiles, wrong values in array
};

以上所有编译问题都是由于它与ANSI标准不兼容,聚合体'foos'具有一些子聚合体,其中一些用括号括起来,而其他一些则没有。因此,如果您删除内部括号以表示数组'tmp',则可以无错误地进行编译。例如:

struct Foo foos[] = {
  {123, tmp},   // works
  {222,  11,22,33 },  // would compile perfectly.
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接