简体   繁体   English

用嵌套结构数组初始化结构

[英]Struct initialization with array of nested structs

I am trying to create a text parsing state machine using a struct. 我正在尝试使用结构创建文本解析状态机。 It seems to work fine for the smaller struct I was using to test it, but the larger strut I require for my final application (modem control) seems to not be represented as I would like in memory. 对于我用来测试它的较小结构,它似乎可以正常工作,但最终应用程序(调制解调器控制)所需的较大支柱似乎并没有像我在内存中那样被表示。

I think the problem lies with initializing this 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;
};

With this macro: 使用此宏:

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

where next_state is: 其中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;
};

The test case that works is: 起作用的测试用例是:

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

output: 输出:

id: 1
id: 2
id: 3

And the larger struct that does not work: 较大的结构不起作用:

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, ""))
};

output: 输出:

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

It would seem that the larger example does not exist in memory. 似乎较大的示例在内存中不存在。 If anyone can point out what I'm doing wrong, that would be awesome. 如果有人能指出我在做什么错,那太好了。

So it looks like the problem is that you are not passing enough arguments to sm_state in the declaration states[0] . 因此,问题似乎在于您没有在声明states[0] sm_state足够的参数传递给sm_state

If you declare like this it works: 如果您这样声明,它将起作用:

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, ""))
};

While we're on the subject, I'd strongly recommend dropping these macros. 当我们讨论这个主题时,强烈建议您删除这些宏。 They don't provide anything but stackoverflow questions cause when the compiler error messages can't be deciphered. 他们什么都没有提供,但是当无法解释编译器错误消息时,就会引起堆栈溢出问题。 I'd recommend initializing each of your variables as I did with states[0] . 我建议像对states[0]一样初始化每个变量。

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

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