C语言 具有未知大小结构数组的结构

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7263723/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:32:53  来源:igfitidea点击:

Struct with array of structs of unknown size

carraysstruct

提问by apann

I've been trying to wrap my head around this the whole day...

我一整天都在努力解决这个问题......

Basically, I have a struct called State that has a name and another one called StateMachine with a name, an array of states and total number of states added:

基本上,我有一个叫做 State 的结构,它有一个名字,另一个叫做 StateMachine,有一个名字、一个状态数组和添加的状态总数:

#include <stdio.h>
#include <stdlib.h>

typedef struct State {
  const char * name;

} State;

typedef struct StateMachine {
  const char * name;

  int total_states;
  State ** states;

} StateMachine;

StateMachine * create_state_machine(const char* name) {
  StateMachine * temp;

  temp = malloc(sizeof(struct StateMachine));

  if (temp == NULL) {
    exit(127);
  }

  temp->name = name;
  temp->total_states = 0;

  temp->states = malloc(sizeof(struct State));
  return temp;
}

void destroy_state_machine(StateMachine* state_machine) {
  free(state_machine);
}

State * add_state(StateMachine* state_machine, const char* name) {
  State * temp;

  temp = malloc(sizeof(struct State));

  if (temp == NULL) {
    exit(127);
  }

  temp->name = name;

  state_machine->states[state_machine->total_states]= temp;
  state_machine->total_states++;

  return temp;
}

int main(int argc, char **argv) {

  StateMachine * state_machine;

  State * init;
  State * foo;
  State * bar;

  state_machine = create_state_machine("My State Machine");

  init = add_state(state_machine, "Init");
  foo  = add_state(state_machine, "Foo");
  bar  = add_state(state_machine, "Bar");

  int i = 0;

  for(i; i< state_machine->total_states; i++) {
    printf("--> [%d] state: %s\n", i, state_machine->states[i]->name);
  }

}

For some reason (read low C-fu / years of ruby/python/php) I'm unable to express the fact that states is an Array of State(s). The above code prints:

出于某种原因(阅读低 C-fu/多年的 ruby​​/python/php)我无法表达状态是一个状态数组的事实。上面的代码打印:

--> [0] state: ~
--> [1] state: Foo
--> [2] state: Bar

What happened with the first state added?

添加第一个状态后发生了什么?

If I malloc the states array on the first state added (e.g. state_machine = malloc(sizeof(temp)); then I get the first value but not the second.

如果我在添加的第一个状态上 malloc 状态数组(例如 state_machine = malloc(sizeof(temp)); 然后我得到第一个值但不是第二个。

Any advices?

有什么建议吗?

This is a C question. I'm using gcc 4.2.1 to compile the sample.

这是一道C题。我正在使用 gcc 4.2.1 来编译示例。

采纳答案by nmichaels

It looks like you're not allocating space for your states in the machine past the first one.

看起来您没有为机器中的第一个状态分配空间。

StateMachine * create_state_machine(const char* name) {
  StateMachine * temp;

  temp = malloc(sizeof(struct StateMachine));

  if (temp == NULL) {
    exit(127);
  }

  temp->name = name;
  temp->total_states = 0;

  temp->states = malloc(sizeof(struct State)); // This bit here only allocates space for 1.
  return temp;
}

You're probably better off putting an array of states of fixed size in the state machine struct. If that's not okay, you'll have to realloc and move the whole set around or allocate chunks and keep track of the current length, or make a linked list.

您最好在状态机结构中放置一组固定大小的状态。如果这不行,您将不得不重新分配并移动整个集合或分配块并跟踪当前长度,或创建一个链表。

Incidentally, init, foo, and bar never get used.

顺便提一下,init、foo 和 bar 永远不会被使用。

Edit: What I'm suggesting looks like this:

编辑:我的建议是这样的:

#define MAX_STATES 128 // Pick something sensible.
typedef struct StateMachine {
  const char * name;
  int total_states;
  State *states[MAX_STATES];
} StateMachine;

回答by Node

It looks like you want to have a variable number of states in each state machine, but you are allocating the memory incorrectly. In create_state_machine, this line:

看起来您希望在每个状态机中拥有可变数量的状态,但是您分配的内存不正确。在create_state_machine,这一行:

temp->states = malloc(sizeof(struct State));

Allocates a single Stateobject, not an array of pointers (which is how you are using it).

分配单个State对象,而不是指针数组(这是您使用它的方式)。

There are two ways you could change this.

有两种方法可以改变这一点。

  1. Declare statesas State states[<some-fixed-size>];but then you cant ever have more than a fixed number of states.
  2. Add another member to indicate how much storage has been allocated for states, so you can keep track of that as well as how much is used (which is what total_statesis being used for).
  1. 声明statesState states[<some-fixed-size>];但是然后你不能拥有超过固定数量的状态。
  2. 添加另一个成员以指示已为 分配了多少存储空间states,以便您可以跟踪该存储空间以及使用了多少(即total_states正在使用的内容)。

The later would look something like this:

后者看起来像这样:

#include <stdlib.h>
#include <string.h>

typedef struct 
{
    const char *name;
} State;

typedef struct 
{
    const char *name;
    int total_states;
    int states_capacity;
    State *states;
} StateMachine;

StateMachine *create_state_machine(const char *name)
{
    StateMachine *temp = malloc(sizeof(StateMachine));
    memset(temp, 0, sizeof(*temp));

    temp->name = name;
    temp->states_capacity = 10;
    temp->states = malloc(sizeof(State) * temp->states_capacity);

    return temp;
}

State *add_state(StateMachine *machine, const char *name)
{
    if (machine->total_states == machine->states_capacity)
    {
        // could grow in any fashion.  here i double the size, could leave
        // half the memory wasted though.
        machine->states_capacity *= 2;

        machine->states = realloc(
            machine->states, 
            sizeof(State) * machine->states_capacity);
    }

    State *state = (machine->states + machine->total_states);
    state->name = name;

    machine->total_states++;

    return state;
}

回答by Homer6

Inside of your add_state function:

在 add_state 函数内部:

temp = malloc(sizeof(struct StateMachine)); 

should be

应该

temp = malloc(sizeof(struct State));

However, even when this is changed, I still get the proper output:

但是,即使更改了,我仍然会得到正确的输出:

--> [0] state: Init
--> [1] state: Foo
--> [2] state: Bar

Perhaps there's nothing wrong with your code. I'm using gcc version 4.4.3

也许您的代码没有任何问题。我正在使用 gcc 版本 4.4.3

回答by John Humphreys - w00te

State ** states;

will create an array of state arrays.

将创建一个状态数组数组。

I haven't read through the whole solution truthfully (gotta run), but you mentioned wanting an array of states - did you possibly want to do:

我没有如实阅读整个解决方案(必须运行),但是您提到想要一系列状态 - 您是否可能想要这样做:

State* states

or

或者

State states[size];

instead? Just food for thought, chances are it wasn't your problem since I didn't fully read it :p

反而?仅供参考,很可能不是您的问题,因为我没有完全阅读它:p

回答by Heisenbug

You're doing a conceptual error:

你在做一个概念性错误:

State ** states;

It's true that you can consider states like an array of pointer to State object, but you are allocating space for just one state. When you do:

确实,您可以将状态视为指向 State 对象的指针数组,但您只是为一个状态分配空间。当你这样做时:

state_machine->states[state_machine->total_states]= temp;

you are doing something wrong if total_states is greater than zero because you are pointing to memory segments that are not been allocated (I'm wondering why you don't get a SEGFAULT). To store a dynamic number of State this way you need a linked list, or to call realloc every state you add(but that's not a good idea). The memory you are allocating with different malloc calls isn't continuous.

如果 total_states 大于零,您就做错了,因为您指向的是未分配的内存段(我想知道为什么您没有得到 SEGFAULT)。要以这种方式存储动态数量的状态,您需要一个链表,或者为您添加的每个状态调用 realloc (但这不是一个好主意)。您使用不同的 malloc 调用分配的内存不是连续的。