如何从一个结构体中调用具有函数指针的函数?

3

我正在努力学习C语言,但遇到了困难。我想要用这个结构体创建一个链表。我试图使用不同的数据类型,包括不同的“led_blinking”函数来创建一个列表。问题是我无法通过在列表中添加函数指针来调用该函数。有谁可以帮我解决这个问题吗?我做错了什么?

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <tm4c123gh6pm.h>
#include <sysctl.h>
#include <gpio.h>

void ledRedTask(){
    GPIO_PORTF_DATA_R = RED;
    delay();
}

void ledGreenTask(){
    GPIO_PORTF_DATA_R = GREEN;
    delay();
}

void ledBlueTask(){
    GPIO_PORTF_DATA_R = BLUE;
    delay();
}

void ledYellowTask(){
    GPIO_PORTF_DATA_R = YELLOW;
    delay();
}

void ledPinkTask(){
    GPIO_PORTF_DATA_R = PINK;
    delay();
}

void ledAquaTask(){
    GPIO_PORTF_DATA_R = AQUA;
    delay();
}

struct taskStruct{
    int taskNumber;
    int taskTime;
    void (*functionTask)(void *);
    struct taskStruct *next;
};

struct taskStruct *head = NULL;
struct taskStruct *curr = NULL;

struct taskStruct* create_list(int taskNumber, void(led_task)(), int delay)
{
    struct taskStruct* ptr = (struct taskStruct*)malloc(sizeof(struct                                                           taskStruct));
    if(NULL == ptr)
    {
        return NULL;
    }
    ptr->taskNumber = taskNumber;
    ptr->taskTime = delay;
    ptr->functionTask = led_task;
    ptr->next = NULL;

    head = curr = ptr;
    return ptr;
}

struct taskStruct* add_to_list(int taskNumber, bool add_to_end, void(ledTask)(), int ticks_delay)
{
    //If list is not created yet, create list
    if(NULL == head)
    {
        return (create_list(taskNumber, ledTask, ticks_delay));
    }

    struct taskStruct *ptr = (struct taskStruct*)malloc(sizeof(struct taskStruct));

    ptr->taskNumber = taskNumber;
    ptr->taskTime = ticks_delay;
    ptr->functionTask = ledTask;
    ptr->next = NULL;

    if(add_to_end)
    {
        curr->next = ptr;
        curr = ptr;
    }
    else
    {
        ptr->next = head;
        head = ptr;
    }
    return ptr;
}

void printTaskList(void)
{
    struct taskStruct *ptr = head;

    while(ptr != NULL)
    {
        ptr = ptr->next;
    }
    return;
}

struct taskStruct* search_in_list(int taskNumber, struct taskStruct **prev)
{
    struct taskStruct *ptr = head;
    struct taskStruct *tmp = NULL;
    bool found = false;

    while(ptr != NULL)
    {
        if(ptr->taskNumber == taskNumber)
        {
            found = true;
            break;
        }
        else
        {
            tmp = ptr;
            ptr = ptr->next;
        }
    }

    if(true == found)
    {
        if(prev)
            *prev = tmp;
        return ptr;
    }
    else
    {
        return NULL;
    }
}

void main(){
    initSystem();

    struct taskStruct* ptr = NULL;

    printTaskList();

    //add new tasks with tasknumber, adding to end of list?, which color should be used?, for how long?
    add_to_list(0, true, ledRedTask, 100);
    add_to_list(1, true, ledRedTask, 100);
    add_to_list(2, true, ledRedTask, 100);
    //add_to_list(2, true, green, 20);
    //add_to_list(3, true, blue, 5000);

    printTaskList();

    while(1){

        ptr = search_in_list(1, NULL);


        __asm(" WFI");
    }
}

这段代码是为Tiva TI Lauchpad开发的。请帮忙。


注意:在嵌入式编程中,将函数指针用作变量是被许多编码标准禁止的,这是有充分理由的。动态内存分配也是一样。嵌入式编程与PC编程非常不同。强制转换 mallocvoid * 的结果总是不明智的。 - too honest for this site
1个回答

2

您需要将函数指针的声明与其分配的函数的原型匹配。您可以通过以下修改来解决此问题。

将您的函数原型更改为以下格式:

void ledRedTask(void) { ... }

void ledGreenTask(void) { ... }

etc...

接着你需要以特定的方式声明函数指针,以匹配这些函数的原型:

void (*functionTask)(void); // <-- NOT void (*functionTask)(void *);

您可以设置指针,即。
 ptr->functionTask = ledTask;

你可以像这样调用它:

ptr->functionTask();

funcname(void *)funcname(void) 的明显区别在于前者期望一个 void 指针参数,而后者则不需要参数。 - alvits

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接