结构与未知大小的结构数组
我一整天都试图绕过这个……
基本上,我有一个名为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
对象,而不是一个指针数组(这就是你如何使用它)。
有两种方法可以改变这种情况。
- 将
states
声明为State states[
但是你不可能拥有超过固定数量的州。]; - 添加另一个成员以指示已为
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调用分配的内存不是连续的。