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