具有未知大小的结构体数组的结构体

发布于 2024-12-02 06:45:51 字数 1840 浏览 0 评论 0原文

我一整天都在试图解决这个问题......

,我有一个名为 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);
  }

}

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

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

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

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

有什么建议吗?

这是一个 C 问题。我正在使用 gcc 4.2。 1 编译示例。

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:

#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:

--> [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.

Any advices?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

眼角的笑意。 2024-12-09 06:45:51

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

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;
}

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

顺便说一下,init、foo 和 bar 从来没有被使用过。

编辑:我的建议看起来像这样:

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

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.

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;
萌化 2024-12-09 06:45:51

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

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

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

有两种方法可以改变这种情况。

  1. states 声明为 State states[]; 但这样你就不能拥有超过固定数量的状态。
  2. 添加另一个成员来指示已为 states 分配了多少存储空间,以便您可以跟踪该存储空间以及使用了多少存储空间(即正在使用的 total_states为了)。

后者看起来像这样:

#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;
}

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:

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

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

There are two ways you could change this.

  1. Declare states as 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_states is being used for).

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;
}
星星的軌跡 2024-12-09 06:45:51

在你的 add_state 函数内部:

temp = malloc(sizeof(struct StateMachine)); 

应该是

temp = malloc(sizeof(struct State));

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

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

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

Inside of your add_state function:

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

月竹挽风 2024-12-09 06:45:51
State ** states;

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

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

State* states

或者

State states[size];

相反?只是供大家思考,很可能这不是你的问题,因为我没有完全阅读它:p

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

暖伴 2024-12-09 06:45:51

您犯了一个概念错误:

State ** states;

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

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

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

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_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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文