简体   繁体   English

结构与未知大小的结构数组

[英]Struct with array of structs of unknown size

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). 由于某种原因(读低C-fu / ruby​​ / python / php年)我无法表达状态是一个状态数组的事实。 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 (eg 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. 这是一个C问题。 I'm using gcc 4.2.1 to compile the sample. 我正在使用gcc 4.2.1编译样本。

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;

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 State object, not an array of pointers (which is how you are using it). 分配单个State对象,而不是指针数组(这是您使用它的方式)。

There are two ways you could change this. 有两种方法可以改变这种情况。

  1. Declare states as State states[<some-fixed-size>]; states声明为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). 添加另一个成员以指示已为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;
}

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

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

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. 确实,您可以将状态视为指向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). 如果total_states大于零,你做错了,因为你指向的是未分配的内存段(我想知道为什么你没有得到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). 要以这种方式存储动态数量的State,您需要一个链表,或者在您添加的每个州调用realloc(但这不是一个好主意)。 The memory you are allocating with different malloc calls isn't continuous. 使用不同malloc调用分配的内存不是连续的。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM