错误:初始值设定项元素在C中不是常量

错误:初始值设定项元素在C中不是常量,c,C,在这里,我试图创建一个状态机,FsmHdlr应该在其中根据状态和事件调用适当的函数。我得到的是上面的错误。如何解决这个问题 S16 handleParamReqEvt(void) { /* doing something */ RETVALUE(ROK); } S16 handleParamRspEvt(param_resp *paramRsp) { /* doing something */ RE

在这里,我试图创建一个状态机,FsmHdlr应该在其中根据状态和事件调用适当的函数。我得到的是上面的错误。如何解决这个问题

   S16 handleParamReqEvt(void)
    {
      /* doing something */
      RETVALUE(ROK);    
    }

    S16 handleParamRspEvt(param_resp *paramRsp) 
    {
      /* doing something */
      RETVALUE(ROK);    
    }

    typedef enum{
      IDLE,
      CONFIGURED,
      MAX_STATE
    }STATE;

    /* Events in CL */
    typedef enum{
      PARAM_REQ,
      PARAM_RSP 
      MAX_EVENT
    }EVENT;

    param_resp *paramMsg;

    S16 FsmHdlr[MAX_STATE][MAX_EVENT] = 
    {
      {
        /* PHY_STATE_IDLE */
        handleParamReqEvt(),           //error :initializer element is not constant
        handleParamRspEvt(paramMsg)    //error: initializer element is not constant
      }
    };

您可以将指向
FsmHdlr[MAX\u STATE][MAX\u EVENT]
的指针声明为全局变量

S16 (*FsmHdlr)[MAX_STATE][MAX_EVENT] = NULL;
main
函数的某个地方,按如下所示将内存分配给全局指针

FsmHdlr = malloc(sizeof(S16 [MAX_STATE][MAX_EVENT]));
   memcpy(FsmHdlr,
         (S16 [MAX_STATE][MAX_EVENT])    {
             {
                 /* PHY_STATE_IDLE */
                handleParamReqEvt(), handleParamRspEvt(paramMsg) 
             }
           },
         sizeof((S16 [MAX_STATE][MAX_EVENT])    {
             {
                 /* PHY_STATE_IDLE */
                handleParamReqEvt(), handleParamRspEvt(paramMsg) 
             }
           })
   );
然后使用
memcpy
复制数组复合文字,如下所示

FsmHdlr = malloc(sizeof(S16 [MAX_STATE][MAX_EVENT]));
   memcpy(FsmHdlr,
         (S16 [MAX_STATE][MAX_EVENT])    {
             {
                 /* PHY_STATE_IDLE */
                handleParamReqEvt(), handleParamRspEvt(paramMsg) 
             }
           },
         sizeof((S16 [MAX_STATE][MAX_EVENT])    {
             {
                 /* PHY_STATE_IDLE */
                handleParamReqEvt(), handleParamRspEvt(paramMsg) 
             }
           })
   );
和取消引用,如下所示

(*FsmHdlr)[0][0];//to access 1st element
(*FsmHdlr)[0][1];//to access 2nd element

听起来您实际上不想在初始化过程中调用该函数(正如您所发现的,对于静态存储变量,您无论如何都不能这样做)。听起来您正在构建一个调度表。您需要的是函数指针

下面介绍如何使用函数指针:

int foo(void) { ... }

int main(void) {
   int (*bar)(void) = foo;
   bar();  // Calls foo
}
由于参数随事件类型的不同而变化,因此2d数组没有多大意义。在你的情况下,我会使用以下方法:

S16 fsm_hdrl_idle_param_req(void)                { ... }
S16 fsm_hdrl_idle_param_rsp(ParamRsp *param_rsp) { ... }
S16 fsm_hdrl_conf_param_req(void)                { ... }
S16 fsm_hdrl_conf_param_rsp(ParamRsp *param_rsp) { ... }

typedef S16 (*FsmReqHdlr)(void);
typedef S16 (*FsmRspHdlr)(ParamRsp*);

typedef struct {
   FsmReqHdlr fsm_req_hdlr;
   FsmRspHdlr fsm_rsp_hdlr;
} FsmHdlrs;

FsmHdlrs fsm_hdlrs_by_state[MAX_STATE] = {
   { fsm_hdrl_idle_param_req, fsm_hdrl_idle_param_rsp },
   { fsm_hdrl_conf_param_req, fsm_hdrl_conf_param_rsp },
};
后来:

fsm_hdlrs_by_state[state].fsm_req_hdlr();

fsm_hdlrs_by_state[state].fsm_rsp_hdlr(param_rsp);

不能在声明期间使用值初始化数组,因为编译时这些值是未知的。 并且,初始化值是由handleParamReqEvt()和handleParamRspEvt(…)返回的值,它们是未知的。 我想您考虑的是指向这些函数的指针,也不是函数值。 因此,您应该使用函数名而不是函数调用,如下所示:

S16 FsmHdlr[MAX_STATE][MAX_EVENT] = 
{
  {
    /* PHY_STATE_IDLE */
    handleParamReqEvt,   //initializer element is NOW constant
    handleParamRspEvt    //initializer element is NOW constant
  }
};
不幸的是,由于错误的数组类型,这将无法编译-现在它不像以前那样是S16[][](或S16**)。 此外,两个指针都是不同类型的指针: -首先是S16(*)(); -第二个是S16(*)(参数分别*); 幸运的是,您可以将它们都存储为void*(指向任何内容的指针),但请记住,在使用之前必须正确地强制转换它们。 对于强制转换简化,可以使用typedef指令声明这些函数的类型

因此,声明+初始化和使用的最终形式将是:

// declaration + initialisation of array
void* FsmHdlr[MAX_STATE][MAX_EVENT] = 
{
  {
    /* PHY_STATE_IDLE */
    handleParamReqEvt,
    handleParamRspEvt
  }
};

// declaration of types
typedef S16 (*reqEvt_ptr)();            //signature of handleParamReqEvt()
typedef S16 (*rspEvt_ptr)(param_resp*); //signature of handleParamRspEvt(param_resp*)

// usage:
// handleParamReqEvt
reqEvt_ptr reqEvt = (reqEvt_ptr)FsmHdlr[/* index here */][PARAM_REQ]; // cast
S16 reqResult = reqEvt(); // call
// handleParamRspEvt
rspEvt_ptr rspEvt = (rspEvt_ptr)FsmHdlr[/* index here */][PARAM_RSP]; // cast
S16 rspResult = rspEvt(/* pointer to paramMsg here */); // call

FsmHdlr
这是全局变量吗?否则这个错误就没有意义了。请提供。什么是
S16
?什么是
RETVALUE
?什么是韩国?是的,FsmFdlr在这里是全球性的。由于代码太长,我无法粘贴整个内容S16是int类型Retvalue(rok)是return 0您是在尝试编译遗留代码还是这些是您的本地更改?对我来说,
FsmHdlr
应该是一个函数指针或函数指针数组,取决于输入。@MAMTHASRI好吧,至少在
c
中是不可能的,除非你存储函数指针而不是它的返回值。OP有两个具有两个不同签名的函数,我认为你的方法不适合。@kiran Biradar,我已经更新了我的答案。