如何在状态机上使用全局变量

时间:2016-08-26 07:38:52

标签: c global-variables state-machine

我做了这个状态机:

 enum states { STATE_ENTRY, STATE_....} current_state;
 enum events { EVENT_OK, EVENT_FAIL,EVENT_REPEAT, MAX_EVENTS } event;
 void (*const state_table [MAX_STATES][MAX_EVENTS]) (void) = {
   { action_entry , action_entry_fail , action_entry_repeat }, /* 
                                                  procedures for state 1 */
  ......}

void main (void){
   event = get_new_event (); /* get the next event to process */
   if (((event >= 0) && (event < MAX_EVENTS))
   && ((current_state >= 0) && (current_state < MAX_STATES))) {
      state_table [current_state][event] (); /* call the action procedure */
      printf("OK 0");
   } else {
      /* invalid event/state - handle appropriately */
         }
}

当我在一个状态中修改全局变量时,全局变量保持不变,我需要在所有状态中使用该变量。你现在有什么问题吗? 我的全局变量就是这个结构:

  #if (CPU_TYPE == CPU_TYPE_32)
     typedef uint32_t word;
     #define word_length 32
     typedef struct BigNumber {
     word words[64];
    } BigNumber;
   #elif (CPU_TYPE == CPU_TYPE_16)
    typedef uint16_t word;
    #define word_length 16
    typedef struct BigNumber {
    word words[128];
    } BigNumber;
   #else
     #error Unsupported CPU_TYPE
  #endif
  BigNumber number1 , number2;

 Here is how I modify:
 //iterator is a number from where I start to modify,
 //I already modified on the same way up to the iterator
 for(i=iterator+1;i<32;i++){
     nr_rand1=661;
     nr_rand2=1601;
     nr_rand3=1873;
     number2.words[i]=(nr_rand1<<21) | (nr_rand2<<11) | (nr_rand3);
  }

3 个答案:

答案 0 :(得分:2)

关于更改number2的代码:

for(i=iterator+1;i<32;i){
    nr_rand1=661;
    nr_rand2=1601;
    nr_rand3=1873;
    number2.words[i]=(nr_rand1<<21) | (nr_rand2<<11) | (nr_rand3);
}

我无法注意到:

  • i永远不会增加,因此只需在无限循环中更改数组的一个元素(iterator+1);
  • 即使i会增加,也只会根据words的值更改iterator数组的一部分(但这可能是预期的行为) )。
  • 除非iterator可以是-1,否则元素words[0]永远不会更改(这也可能是预期的行为)。

我会检查这是否真的是你打算做的。

如果你确定它只是一个可见性问题(因为你说当你宣布它是按照预期工作的本地时),我能想到的另一件事就是你有一个文件中的功能和另一个文件中的主要功能(或您在其中进行检查的地方)。

然后在两个文件中包含相同的.h标题,最后(由于您正在使用的链接器)使用两个不同的number2,因为您没有将其声明为{{ 1}}在两个文件中的一个。 您的编译器(或者更好的是链接器)应该(至少)警告过您,是否检查了编译消息?

答案 1 :(得分:1)

这是为了防止您想要更改定义FSM的方法。我将向您展示一个例子;说你有以下FSM:

enter image description here

您可以将其表示为:

void function process() {
   fsm {
     fsmSTATE(S) {
       /* do your entry actions heare */
       event = getevent();
       /* do you actions here */
       if (event.char == 'a') fsmGOTO(A); 
       else fsmGOTO(E);
     }

     fsmSTATE(A) {
       event = getevent();
       if (event.char == 'b' || event.char == 'B') fsmGOTO(B); 
       else fsmGOTO(E);
     }

     fsmSTATE(B) {
       event = getevent();
       if (event.char == 'a' ) fsmGOTO(A); 
       else fsmGOTO(E);
     }
     fsmSTATE(E) {
       /* done with the FSM. Bye bye! */
     }
   }
}

我声称(但我相信有人会不同意)这比使用表格更简单,更易读并直接传达FSM的结构。即使我没有放置图像,绘制FSM图也会相当容易。

要做到这一点,你只需要定义fsmXXX内容如下:

#define fsm            
#define fsmGOTO(x)    goto fsm_state_##x
#define fsmSTATE(x)   fsm_state_##x :

答案 2 :(得分:1)

这不是答案 - 而是评论。但它太大了,不适合评论字段,所以我暂时在这里发布。

问题中发布的代码不足以找到根本原因。您需要发布一个显示问题的最小但完整的示例。

类似的东西:

#include<stdio.h>
#include<stdlib.h>
#include <stdint.h>

typedef uint32_t word;
#define word_length 32
typedef struct BigNumber {
  word words[4];
} BigNumber;

BigNumber number2;

enum states { STATE_0, STATE_1} current_state;
enum events { EVENT_A, EVENT_B } event;

void f1(void)
{
  int i;
  current_state = STATE_1;
  for (i=0; i<4; ++i) number2.words[i] = i;
}

void f2(void)
{
  int i;
  current_state = STATE_0;
  for (i=0; i<4; ++i) number2.words[i] = 42 + i*i;
}

void (*const state_table [2][2]) (void) =
{
    { f1 , f1 },
    { f2 , f2 }
};


int main (void){
  current_state = STATE_0;

  event = EVENT_A;
  state_table [current_state][event] (); /* call the action procedure */
  printf("%u %u %u %u\n", number2.words[0], number2.words[1], number2.words[2], number2.words[3]);

  event = EVENT_B;
  state_table [current_state][event] (); /* call the action procedure */
  printf("%u %u %u %u\n", number2.words[0], number2.words[1], number2.words[2], number2.words[3]);

  return 0;
}

以上内容可视为最小和完整。现在使用您自己的一些函数更新此代码并将其作为问题发布(如果它仍然失败)。

我的代码没有失败。

输出:

0 1 2 3
42 43 46 51