使用嵌套结构数组进行struct初始化

时间:2014-11-10 11:45:35

标签: c arrays macros struct

我正在尝试使用struct创建一个文本解析状态机。它似乎适用于我用来测试它的较小结构,但我最终应用程序(调制解调器控制)所需的更大的支撑似乎没有像我想的那样在内存中表示。

我认为问题在于初始化这个结构:

struct state
{
    size_t const id;
    size_t(* const callback)(void*);
    void* const callback_arg;
    char const* const out_pattern;
    size_t const out_pattern_length;
    unsigned long int timeout;
    size_t const timeout_state;
    size_t const next_states_length;
    struct next_state const* next_states;
};

使用此宏:

#define sm_state(id, callback, callback_arg, out_str, out_str_length, timeout, \
timeout_state, next_states_length, ...) \
{id, callback, callback_arg, out_str, out_str_length, timeout, \
timeout_state, next_states_length, \
(struct next_state const[next_states_length]){__VA_ARGS__}}

其中next_state是:

#define sm_next_state(next_state_id, in_pattern_length, in_pattern) \
{next_state_id, in_pattern_length, in_pattern}

struct next_state
{
    size_t const next_state;
    size_t const in_pattern_length;
    char const* in_pattern;
};

有效的测试用例是:

enum states_enum
{
    fruit = 1,
    vegitable,
    error,
};

struct state const states[] = {
    //          id          callback        callback argument   pattern to be sent on entry         patlen  timeout     t/o state   next states count   next_states
    sm_state(   fruit,      NULL,           NULL,               "hello, pick a fruit\n",            20,     100000UL,   1,          3,                  sm_next_state(fruit, 4, "pear"),        sm_next_state(vegitable, 5, "apple"),       sm_next_state(error, 6, "turnip")),
    sm_state(   vegitable,  NULL,           NULL,               "now pick a vegetable\n",           21,     100000UL,   3,          3,                  sm_next_state(fruit, 7, "cabbage"),     sm_next_state(vegitable, 6, "potato"),      sm_next_state(error, 6, "turnip")),
    sm_state(   error,      NULL,           NULL,               "error, you entered turnip...\n",   29,     100000UL,   1,          3,                  sm_next_state(fruit, 3, "one"),         sm_next_state(vegitable, 3, "two"),         sm_next_state(error, 6, "turnip"))
};

int i = 0;
while (i < 3)
{
    printf("id: %d\n", states[i].id);
    ++i;
}

输出:

id: 1
id: 2
id: 3

更大的结构不起作用:

enum bluetooth_states_enum
{
    bt_off = 1,
    bt_on,
    bt_set_echo_off,
    bt_set_auto_answer,
    bt_set_ignore_dsr,
    bt_set_spp,
    bt_set_io_cap,
    bt_set_mitm_protection,
    bt_write,
    bt_reset,
    bt_set_firendly_name,
    bt_set_connectable,
    bt_set_key,
    bt_listening,
    bt_answer,
    bt_in_call,
    bt_hup,
    bt_error,
};

struct state const states[] = {
    sm_state(   bt_off,                 NULL, NULL, "",             0,      -1,         bt_off,     0,),
    sm_state(   bt_on,                  NULL, NULL, "AT\r",         3,      100000UL,   bt_error,   2,          sm_next_state(bt_set_echo_off, 2, "OK"),            sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_echo_off,        NULL, NULL, "ATE0\r",       5,      100000UL,   bt_error,   2,          sm_next_state(bt_set_auto_answer, 2, "OK"),         sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_auto_answer,     NULL, NULL, "ATS0=2\r",     7,       100000UL,  bt_error,   2,          sm_next_state(bt_set_ignore_dsr, 2, "OK"),          sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_ignore_dsr,      NULL, NULL, "ATS102=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_spp, 2, "OK"),                 sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_spp,             NULL, NULL, "ATS102=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_io_cap, 2, "OK"),              sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_io_cap,          NULL, NULL, "ATS321=0\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_mitm_protection, 2, "OK"),     sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_mitm_protection, NULL, NULL, "ATS322=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_write, 2, "OK"),                   sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_write,               NULL, NULL, "AT&W\r",       5,      100000UL,   bt_error,   2,          sm_next_state(bt_reset, 2, "OK"),                   sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_reset,               NULL, NULL, "ATZ\r",        4,      100000UL,   bt_error,   2,          sm_next_state(bt_set_firendly_name, 2, "OK"),       sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_firendly_name,   NULL, NULL, "AT+BTF=\"Friendly Name\"\r", 18, 100000UL, bt_error, 2,    sm_next_state(bt_set_connectable, 2, "OK"),         sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_connectable,     NULL, NULL, "AT+BTP\r",     7,      100000UL,   bt_error,   2,          sm_next_state(bt_set_key, 2, "OK"),                 sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_key,             NULL, NULL, "AT+BTK=\"8475\"\r", 14, 100000UL, bt_error, 2,          sm_next_state(bt_listening, 2, "OK"),               sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_listening,           NULL, NULL, "",             0,      -1,     0,          1,          sm_next_state(bt_answer, 4, "RING")),
    sm_state(   bt_answer,              NULL, NULL, "ATA\r",        4,      100000UL,   bt_error,   2,          sm_next_state(bt_in_call, 7, "CONNECT"),            sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_in_call,             NULL, NULL, "",             0,      100000UL, bt_error, 2,          sm_next_state(bt_set_connectable, 10, "NO CONNECT"), sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_error,               NULL, NULL, "",             0,      -1,         bt_off,     1,          sm_next_state(bt_off, 0, ""))
};

输出:

id: 1820602156
id: 7
id: -1
id: 1973037073
id: 0
id: 0
id: 123336558
id: 0
id: 0
id: 0
id: 736
id: 760826203
id: 3108
id: -1322777276
id: 1
id: 7916
id: 152

似乎更大的例子在内存中不存在。如果有人能指出我做错了什么,那就太棒了。

1 个答案:

答案 0 :(得分:1)

所以看起来问题是你没有在声明sm_state中向states[0]传递足够的参数。

如果你这样宣布它是有效的:

struct state const states[] = {
    {bt_off, NULL, NULL, "", 0, -1, bt_off, 0},
    sm_state(   bt_on,                  NULL, NULL, "AT\r",         3,      100000UL,   bt_error,   2,          sm_next_state(bt_set_echo_off, 2, "OK"),            sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_echo_off,        NULL, NULL, "ATE0\r",       5,      100000UL,   bt_error,   2,          sm_next_state(bt_set_auto_answer, 2, "OK"),         sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_auto_answer,     NULL, NULL, "ATS0=2\r",     7,       100000UL,  bt_error,   2,          sm_next_state(bt_set_ignore_dsr, 2, "OK"),          sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_ignore_dsr,      NULL, NULL, "ATS102=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_spp, 2, "OK"),                 sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_spp,             NULL, NULL, "ATS102=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_io_cap, 2, "OK"),              sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_io_cap,          NULL, NULL, "ATS321=0\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_set_mitm_protection, 2, "OK"),     sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_mitm_protection, NULL, NULL, "ATS322=1\r",   9,      100000UL,   bt_error,   2,          sm_next_state(bt_write, 2, "OK"),                   sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_write,               NULL, NULL, "AT&W\r",       5,      100000UL,   bt_error,   2,          sm_next_state(bt_reset, 2, "OK"),                   sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_reset,               NULL, NULL, "ATZ\r",        4,      100000UL,   bt_error,   2,          sm_next_state(bt_set_firendly_name, 2, "OK"),       sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_firendly_name,   NULL, NULL, "AT+BTF=\"Friendly Name\"\r", 18, 100000UL, bt_error, 2,    sm_next_state(bt_set_connectable, 2, "OK"),         sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_connectable,     NULL, NULL, "AT+BTP\r",     7,      100000UL,   bt_error,   2,          sm_next_state(bt_set_key, 2, "OK"),                 sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_set_key,             NULL, NULL, "AT+BTK=\"8475\"\r", 14, 100000UL, bt_error, 2,          sm_next_state(bt_listening, 2, "OK"),               sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_listening,           NULL, NULL, "",             0,      -1,     0,          1,          sm_next_state(bt_answer, 4, "RING")),
    sm_state(   bt_answer,              NULL, NULL, "ATA\r",        4,      100000UL,   bt_error,   2,          sm_next_state(bt_in_call, 7, "CONNECT"),            sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_in_call,             NULL, NULL, "",             0,      100000UL, bt_error, 2,          sm_next_state(bt_set_connectable, 10, "NO CONNECT"), sm_next_state(bt_error, 5, "ERROR")),
    sm_state(   bt_error,               NULL, NULL, "",             0,      -1,         bt_off,     1,          sm_next_state(bt_off, 0, ""))
};

虽然我们已经讨论过此主题,但我强烈建议您删除这些宏。他们不提供任何东西,但堆栈溢出问题会导致编译器错误消息无法解密。我建议您像使用states[0]一样初始化每个变量。