简体   繁体   English

如何将两个灵活的数组放在一个结构中?

[英]How can i put two flexible array in a single struct?

I'm newbie in programming and learning about struct, when trying to put two flexible array in a single struct they give me a error, why i can't put two array in a single struct?我是编程和学习结构的新手,当试图将两个灵活数组放入一个结构中时,他们给了我一个错误,为什么我不能将两个数组放入一个结构中? I created a pokemon example to test a array in struct but only *pokemon_name[] works, why?我创建了一个 pokemon 示例来测试 struct 中的数组,但只有 *pokemon_name[] 有效,为什么?

#include <stdio.h>

void main()
{
  struct pokemon
  {
    int first_generation;
    char *pokemon_type[];
    char *pokemon_name[];
  } number_pokedex[438];

  number_pokedex[23].pokemon_name[5] = "Arbok";
  number_pokedex[23].pokemon_type[6] = "Poison";
  number_pokedex[23].first_generation = 1;

  printf("Name of the pokemon: %s\n", number_pokedex[23].pokemon_name[5]);
  printf("Type of the pokemon: %s\n", number_pokedex[23].pokemon_type[6]);
  printf("From first generation?: %d\n", number_pokedex[23].first_generation);
}

Why the error message ?为什么会出现错误信息?

The C standard says in section 6.7.2.1 / 18: C 标准在第 6.7.2.1 / 18 节中说:

As a special case, the last element of a structure with more than one named member may have an incomplete array type;作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型; this is called a flexible array member.这称为灵活数组成员。 In most situations, the flexible array member is ignored.在大多数情况下,灵活的数组成员会被忽略。 In particular, the size of the structure is as if the flexible array member were omitted except that it may have more trailing padding than the omission would imply.特别是,结构的大小就像省略了灵活的阵列成员,只是它可能具有比省略所暗示的更多的尾随填充。

In your case, you have such a flexible array that is not the last element of the struct, and hence the error.在您的情况下,您有一个如此灵活的数组,它不是结构的最后一个元素,因此是错误。

Why doesn't C allow more than one flexible array member ?为什么 C 不允许多个灵活的数组成员?

The behavior of a struct with a flexible array, is defined so that it works as if the flexible array starts just after the code of the struct.具有灵活数组的结构的行为被定义为使其工作时好像灵活数组在结构的代码之后开始一样。

 +--------------------------------+----+----+----+----+
 | struct without flexible array  |f[0]|f[1]|f[2]|... |
 +--------------------------------+----+----+----+----+

So you can write code such as:所以你可以编写如下代码:

  struct test
  {
    int a;
    int flex[];
  } *pt, array[10];

  static struct test t={ 1, {2,3,4}};
  printf ("%x %x %x\n", &t, &t.flex[0], &t.flex[3]);

  pt = malloc(sizeof(struct test)+20*sizeof(int)); 
  printf ("%x %x\n", pt, &pt->flex[0]);

The problem is that you have to know how many elements are reserved for the flexible array (either statically reserved or dynamically allocated).问题是您必须知道为灵活数组保留了多少元素(静态保留或动态分配)。 If C would allow several flexible arrays, this kind of behavior would no longer be possible, since the compiler would not know where the second flexible array would start.如果 C 允许多个灵活数组,这种行为将不再可能,因为编译器不知道第二个灵活数组从哪里开始。

Alterantive替代品

Now you can very well rewrite your code by using more robust fixed size arrays, or using dynamic arrays by the means of a pointer to pointers.现在您可以通过使用更健壮的固定大小数组或通过指向指针的指针使用动态数组来很好地重写您的代码。

struct pokemon
{
  int first_generation;
  char **pokemon_type;
  char **pokemon_name;
} number_pokedex[438];

In this case, you'd have to inialize the char** pointers by allocating an array of sufficient size:在这种情况下,您必须通过分配足够大小的数组来初始化char**指针:

// assuming that no more than 10 elements in item 23.  
number_pokedex[23].pokemon_name = calloc (10, sizeof(char*));
number_pokedex[23].pokemon_type = calloc (10, sizeof(char*));

You'd also need to free the arrays when no longer needed.您还需要在不再需要时释放阵列。 Finally you'd have to take extra care when copying struct elements, since you'd clone the pointers.最后,您在复制结构元素时必须格外小心,因为您会克隆指针。

While Christophe gives a perfectly sound traditional answer, you might want to be aware of an alternative.虽然Christophe给出了一个完美的传统答案,但您可能希望了解替代方案。 Instead of an array of pointers, if you're willing to limit the length of the names, you could use an array of arrays instead.如果您愿意限制名称的长度,而不是指针数组,则可以使用数组数组。

typedef char name_type[20];

struct pokemon
{
  int first_generation;
  name_type *pokemon_type, *pokemon_name;
} number_pokedex[438];

void b() {
  number_pokedex[23].pokemon_name = calloc (10, sizeof(name_type));
  number_pokedex[23].pokemon_type = calloc (10, sizeof(name_type));
}

This says your names are 20 bytes, and your arrays are 200 bytes: 10 elements of 20 bytes each.这表示您的名称是 20 个字节,您的数组是 200 个字节:10 个元素,每个元素 20 个字节。 Unlike the array-of-pointers technique, here calloc allocates not pointers, but arrays, so you have only one allocation and one deallocation.与指针数组技术不同,这里的calloc分配的不是指针,而是数组,因此您只有一次分配和一次释放。

IMO an array of arrays is easier to use: when it comes time to populate the name, the storage is already allocated, and when it comes time to free the array, you don't have to chase the pointer for each element. IMO 数组数组更易于使用:当需要填充名称时,已经分配了存储空间,并且当需要释放数组时,您不必追逐每个元素的指针。

A common objection is that this technique requires the name size to be established at compile-time, making it less "flexible".一个普遍的反对意见是,这种技术需要在编译时确定名称大小,使其“不灵活”。 That's less of an issue than it might seem, though, because wherever the name appears there is an implied limit, whether it's a field in a GUI or a column in a database or the width of a terminal or the size of the window on an envelope.不过,这并没有看起来那么严重,因为无论名称出现在何处,都有一个隐含的限制,无论是 GUI 中的字段还是数据库中的列,还是终端的宽度或窗口的大小信封。 Might as well decide how big your names are, and get on with it.不妨决定你的名字有多大,然后继续。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 给定结构中灵活数组成员的绝对地址,我如何获得该结构的绝对地址? - Given the absolute address of the flexible array member in a struct, how can I get the absolute address of the struct? 如何安全地将两个可变大小的数据类型(结构)放在单个结构中? - How do I safely put two variable sized datatypes (structs) in a single struct? 如何在堆栈上分配具有灵活数组成员的结构 - How to allocate a struct with a flexible array member on the stack 为什么单个(灵活数组)成员结构声明仅由 [0] 支持而不是 []? - Why single (flexible array) member struct declaration is only supported by [0] and not []? 使用灵活数组初始化结构 - Initialize struct with flexible array 这个 C 程序是否定义了两个结构定义,涉及一个灵活的数组成员? - Is this C program with two struct definitions, involving a flexible array member, defined? 具有灵活数组成员的结构的“数组” - “Array” of struct with flexible array member 如何在 rodata 中初始化一个灵活的数组并创建一个指向它的指针? - How can I initialize a flexible array in rodata and create a pointer to it? 无效使用灵活数组 - 灵活结构数组作为另一个结构的成员 - invalid use of flexible array -flexible struct array as a member of another struct 具有灵活数组成员的结构的大小 - Size of a struct with flexible array member
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM