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

时间:2011-08-31 21:34:17

标签: c arrays struct

我一整天都试图绕过这个......

基本上,我有一个名为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的年份)我无法表达状态是一个状态数组的事实。上面的代码打印出来:

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

第一个州添加了什么?

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

有任何建议吗?

这是一个C问题。我正在使用gcc 4.2.1编译样本。

5 个答案:

答案 0 :(得分:7)

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

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;

答案 1 :(得分:5)

看起来你想在每个状态机中拥有可变数量的状态,但是你正在错误地分配内存。在create_state_machine中,此行:

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

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

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

  1. states声明为State states[<some-fixed-size>];但是你不能拥有超过固定数量的州。
  2. 添加另一个成员以指示已为states分配了多少存储空间,因此您可以跟踪该存储空间以及使用的数量(这是total_states正在使用的内容)。
  3. 后者看起来像这样:

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

答案 2 :(得分:3)

你的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

答案 3 :(得分:1)

State ** states;

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

我没有真实地阅读整个解决方案(已经运行),但你提到想要一系列状态 - 你可能想要这样做:

State* states

State states[size];

代替?只是值得深思,有机会不是你的问题,因为我没有完全阅读它:p

答案 4 :(得分:1)

你在做一个概念错误:

State ** states;

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

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

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