我是一个电子产品的人,请好好对待我。
我正在阅读有关8位微控制器实时操作系统的this文章。我遇到了一个奇怪的观点,我遇到了这个函数。我无法理解它在做什么。我知道void
意味着“没有类型”。我猜测(*Task)
是投射。我真的不知道那之后那些括号是做什么的。
这个函数的论点是什么?
另外,我无法理解*(int*)((NewTCB->Stack) + (STACK_DEPTH-2)) = (int)Task;
做了什么?
答案 0 :(得分:7)
void (*Task)()
实际上是函数指针。基本上它是这样说的:“参数名称是Task
,它是一个返回void
的函数,并且(因为这不是c ++),它接受任意数量的参数。
所以你可以这样称呼它:
void my_task() {
/* do something */
}
TaskCreate(my_task);
当然,编写void my_task(void) {
也是安全的。在编码c时,我个人更喜欢明确地说“没有参数”
最后,*(int*)((NewTCB->Stack) + (STACK_DEPTH-2)) = (int)Task;
正在做一些施法魔法。
让我们解读它:
(int)Task
首先将Task
转换为int
(这是有问题的,但对于您的特定架构/操作系统可能没问题。就个人而言,我会使用long
来安全)。
((NewTCB->Stack) + (STACK_DEPTH-2))
正在对NewTCB->Stack
进行一些简单的算术,以获取指向TCB
堆栈中某个位置的指针。
*(int*)
说“将其转换为int *
,然后依赖(读取或写入)它指向的位置。
我们可以更简单地写下这个:
int f = (int)Task;
int s = ((NewTCB->Stack) + (STACK_DEPTH-2)); /* I don't know the type of `NewTCB->Stack`, so we'll pretend 'int' for now */
int *stack_ptr = (int*)s;
*stack_ptr = f;
可能更清楚。
关注:我想指出我使用的方法倾向于使用函数指针,因为语法有时会有点混乱。我发现这种方法非常有用。基本上我喜欢为函数指针创建一个typedef
并使用它,我发现它更容易正确:
例如:
/* typedef func_t to be a pointer to a function taking no arguments and returning void */
typedef void (*func_t)(void);
然后......
void CreateTask(func_t task) {
/* same work as your example, just a little easier to read */
}
答案 1 :(得分:0)
*(int*)((NewTCB->Stack) + (STACK_DEPTH-2)) = (int)Task;
获取Task
并将其转换为整数。然后,它找到NewTCB
的堆栈(某种形式的数组)。它需要该堆栈并找到倒数第二个成员。然后它将其视为整数变量的地址,并将转换后的Task分配给该地址的变量。
NewTCB->stack
使用C ++指针到成员的语法。 NewTCB
是指向TCB
对象的指针,TCB
个对象显然具有Stack属性。
向其添加STACK_DEPTH - 2
与编写(NewTCB->Stack)[STACK_DEPTH - 2]
(在明文中:NewTCB->Stack
:在索引STACK_DEPTH - 2
处获取对象)相同,除了堆栈对象是动态分配的数组。登记/>
如果NewTCB->Stack
的长度为STACK_DEPTH
,则索引为STACK_DEPTH - 2
的对象为倒数第二个成员(基于0的索引)。
其余的只是处理将Task移动到适当位置所需的转换。
答案 2 :(得分:0)
Evan Teran的回答是正确的。我将通过代码来扩展它,它似乎是指向在选择运行任务时执行的函数的指针。
至于*(int*)((NewTCB->Stack) + (STACK_DEPTH-2)) = (int)Task;
我假设你的环境int
是16位?如果是这样,这将是-2。此代码在此结构中保存了Task的'main'函数的地址(这很奇怪,因为它已经保存在->Task
成员中,但可能有一个很好的理由)