"assignment of read-only member" 分配给结构的非 const 成员时出错
"assignment of read-only member" error when assigning to non const member of a struct
我正在尝试在 C 中创建 FSM。我正在使用 C 的 STATE 模式的变体here。问题是我身处嵌入式世界,它们让我遵守一些安全关键规则。这些规则之一说我不能使用非常量指针指向函数,所以我创建了我的 fsm 是这样的:
typedef struct tFsm* tFsmPtr;
/* PLEASE NOTE: This is a non const struct with its member
* being a const pointer to a function. */
typedef struct
{
void (*const raise)(tFsmPtr);
} tEvent;
struct tFsm
{
/* Because the tEvent type is non const,
* I can modify these fields */
tEvent start;
tEvent started;
tEvent stop;
tEvent stopped;
};
static void DefaultInvalidEventCallback(tFsmPtr fsm)
{
/* Raise an error */
}
static struct tFsm m_fsm = {
.start = { .raise = &DefaultInvalidEventCallback },
.started = { .raise = &DefaultInvalidEventCallback },
.stop = { .raise = &DefaultInvalidEventCallback },
.stopped = { .raise = &DefaultInvalidEventCallback }
};
到目前为止没有错误。问题是当我尝试修改 struct tFsm
的任何字段时,它会抱怨。例如这段代码:
void ResetFsm( tFsmPtr fsm )
{
fsm->start = (tEvent){ .raise = &DefaultInvalidEventCallback };
fsm->started = (tEvent){ .raise = &DefaultInvalidEventCallback };
fsm->stop = (tEvent){ .raise = &DefaultInvalidEventCallback };
fsm->stopped = (tEvent){ .raise = &DefaultInvalidEventCallback };
}
编译器抱怨说:
prog.c: In function 'ResetFsm':
prog.c:32:22: error: assignment of read-only member 'start'
fsm->start = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
prog.c:33:22: error: assignment of read-only member 'started'
fsm->started = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
prog.c:34:22: error: assignment of read-only member 'stop'
fsm->stop = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
prog.c:35:22: error: assignment of read-only member 'stopped'
fsm->stopped = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
我的问题是:
你能告诉我编译器为什么在这里抱怨吗?
有没有办法在这里使用指向函数的 const 指针?
提前致谢。
结构 tEvent
的成员 raise
,定义为常量:
void (*const raise)(tFsmPtr);
这意味着只能初始化整个结构:
tEvent s = { DefaultInvalidEventCallback };
但整个结构的赋值不是:
tEvent a;
a = s;
这当然适用于任何具有结构 tEvent
作为其成员的结构,例如:struct tFsm
,如您的示例所示
对于任何具有 const
成员的结构,您只能在初始化结构时设置该成员。您不能在 run-time 中更改它,原因与您不能这样做的原因相同:
const int x=1;
x=2;
您已经创建了一个 immutable object。
由于不允许使用 non-constant 函数指针,函数 ResetFsm
没有任何意义,需要删除。没办法把它写得有意义。
你可以做的是:
struct tFsm CreateDefaultFsm (void)
{
return (struct tFsm)
{
.start = (tEvent){ .raise = &DefaultInvalidEventCallback },
.started = (tEvent){ .raise = &DefaultInvalidEventCallback },
.stop = (tEvent){ .raise = &DefaultInvalidEventCallback },
.stopped = (tEvent){ .raise = &DefaultInvalidEventCallback },
};
}
您还可以创建类似的复制函数等。所有作用于该结构的函数都必须创建它的新副本。
我正在尝试在 C 中创建 FSM。我正在使用 C 的 STATE 模式的变体here。问题是我身处嵌入式世界,它们让我遵守一些安全关键规则。这些规则之一说我不能使用非常量指针指向函数,所以我创建了我的 fsm 是这样的:
typedef struct tFsm* tFsmPtr;
/* PLEASE NOTE: This is a non const struct with its member
* being a const pointer to a function. */
typedef struct
{
void (*const raise)(tFsmPtr);
} tEvent;
struct tFsm
{
/* Because the tEvent type is non const,
* I can modify these fields */
tEvent start;
tEvent started;
tEvent stop;
tEvent stopped;
};
static void DefaultInvalidEventCallback(tFsmPtr fsm)
{
/* Raise an error */
}
static struct tFsm m_fsm = {
.start = { .raise = &DefaultInvalidEventCallback },
.started = { .raise = &DefaultInvalidEventCallback },
.stop = { .raise = &DefaultInvalidEventCallback },
.stopped = { .raise = &DefaultInvalidEventCallback }
};
到目前为止没有错误。问题是当我尝试修改 struct tFsm
的任何字段时,它会抱怨。例如这段代码:
void ResetFsm( tFsmPtr fsm )
{
fsm->start = (tEvent){ .raise = &DefaultInvalidEventCallback };
fsm->started = (tEvent){ .raise = &DefaultInvalidEventCallback };
fsm->stop = (tEvent){ .raise = &DefaultInvalidEventCallback };
fsm->stopped = (tEvent){ .raise = &DefaultInvalidEventCallback };
}
编译器抱怨说:
prog.c: In function 'ResetFsm':
prog.c:32:22: error: assignment of read-only member 'start'
fsm->start = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
prog.c:33:22: error: assignment of read-only member 'started'
fsm->started = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
prog.c:34:22: error: assignment of read-only member 'stop'
fsm->stop = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
prog.c:35:22: error: assignment of read-only member 'stopped'
fsm->stopped = (tEvent){ .raise = &DefaultInvalidEventCallback };
^
我的问题是: 你能告诉我编译器为什么在这里抱怨吗? 有没有办法在这里使用指向函数的 const 指针?
提前致谢。
结构 tEvent
的成员 raise
,定义为常量:
void (*const raise)(tFsmPtr);
这意味着只能初始化整个结构:
tEvent s = { DefaultInvalidEventCallback };
但整个结构的赋值不是:
tEvent a;
a = s;
这当然适用于任何具有结构 tEvent
作为其成员的结构,例如:struct tFsm
,如您的示例所示
对于任何具有 const
成员的结构,您只能在初始化结构时设置该成员。您不能在 run-time 中更改它,原因与您不能这样做的原因相同:
const int x=1;
x=2;
您已经创建了一个 immutable object。
由于不允许使用 non-constant 函数指针,函数 ResetFsm
没有任何意义,需要删除。没办法把它写得有意义。
你可以做的是:
struct tFsm CreateDefaultFsm (void)
{
return (struct tFsm)
{
.start = (tEvent){ .raise = &DefaultInvalidEventCallback },
.started = (tEvent){ .raise = &DefaultInvalidEventCallback },
.stop = (tEvent){ .raise = &DefaultInvalidEventCallback },
.stopped = (tEvent){ .raise = &DefaultInvalidEventCallback },
};
}
您还可以创建类似的复制函数等。所有作用于该结构的函数都必须创建它的新副本。