1

我是一个电子人,所以请善待我。

我正在阅读这篇关于 8 位微控制器的实时操作系统的文章。我遇到了这个函数,有一个看起来很奇怪的论点。我无法理解它在做什么。我知道这void意味着“没有类型”。我猜这(*Task)就是选角。我真的不知道那些括号在那之后做了什么。

这个函数的参数包括什么?

另外,我不明白它是*(int*)((NewTCB->Stack) + (STACK_DEPTH-2)) = (int)Task;做什么的?

在此处输入图像描述

4

3 回答 3

7

void (*Task)()实际上是一个函数指针。基本上它是在说:“参数名称是Task,它是一个返回的函数,void并且(因为这是 c 而不是 c++)接受任意数量的参数。

所以你可以这样称呼它:

void my_task() {
    /* do something */
}

TaskCreate(my_task);

当然,写起来也是安全的void my_task(void) {。在编码c时,我个人更喜欢明确地说“没有参数”

最后,*(int*)((NewTCB->Stack) + (STACK_DEPTH-2)) = (int)Task;正在做一些施法魔法。

让我们剖析一下:

(int)Task首先转换Taskint(这是有问题的,但对于您的特定架构/操作系统可能没问题。就个人而言,我会使用 along以确保安全)。

((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 */
}
于 2012-06-07T15:29:01.693 回答
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->Stackget object at index STACK_DEPTH - 2),除了堆栈对象是动态分配的数组。
如果NewTCB->Stack有 length STACK_DEPTH,则 index 处的对象STACK_DEPTH - 2是倒数第二个成员(从 0 开始的索引)。
其余的只是处理将 Task 移动到适当位置所需的转换。

于 2012-06-07T15:31:42.137 回答
0

埃文·特兰的回答是正确的。我会扩展它,从代码中它似乎是一个指向在选择运行任务时执行的函数的指针。

至于*(int*)((NewTCB->Stack) + (STACK_DEPTH-2)) = (int)Task;

我假设在您的环境int中是 16 位?如果是这样,这将是-2。这段代码在这个结构中保存了任务的'main'函数的地址(这很奇怪,因为它已经保存在->Task成员中,但可能有一个很好的理由)

于 2012-06-07T15:34:27.563 回答