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

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

基本上,我有一个名为State的结构,它有一个名称,另一个名为StateMachine,带有名称,状态数组和添加的状态总数:

#include  #include  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; itotal_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编译样本。

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

 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; 

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

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

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

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

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

后者看起来像这样:

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

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

 State ** states; 

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

我没有真实地阅读整个解决方案(必须运行),但是你提到想要一系列状态 – 你是否想要做:

 State* states 

要么

 State states[size]; 

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

你在做一个概念错误:

 State ** states; 

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

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

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