函数指针数组作为C结构的成员

时间:2017-11-15 07:36:43

标签: c function-pointers

我构建了以下C示例,试图模拟可用于小型ARM微控制器的简单通用驱动程序代码:

#include <stdio.h>
#include <string.h>

typedef unsigned char uint8_t;
typedef void (*generic_func_t)(uint8_t);

typedef struct {
        generic_func_t init;
        generic_func_t open;
        generic_func_t read;
        generic_func_t write;
        generic_func_t close;
        generic_func_t exit;
} driver_t;

void USB_init(uint8_t x)
{
        /* here body of this f-n */
        printf("USB_open 0x%x\n", x);
}

void USB_open(uint8_t x)
{
        /* here body of this f-n */
        printf("USB_open 0x%x\n", x);
}

void USB_read(uint8_t x)
{
        /* here body of this f-n */
        printf("USB_read 0x%x\n", x);
}

void USB_write(uint8_t x)
{
        /* here body of this f-n */
        printf("USB_write 0x%x\n", x);
}

void USB_close(uint8_t x)
{
        /* here body of this f-n */
        printf("USB_close 0x%x\n", x);
}

void USB_exit(uint8_t x)
{
        /* here body of this f-n */
        printf("USB_close 0x%x\n", x);
}

typedef struct driver_t USB_driver;

#if 1
        USB_driver.init = &USB_init;
        USB_driver.open = &USB_open;
        USB_driver.read  = &USB_read;
        USB_driver.write = &USB_write;
        USB_driver.close = &USB_close;
        USB_driver.exit  = &USB_exit;
#endif

#if 1
void main(void) {}
#endif
#if 0
void main(void) {
        USB_driver.init(0x01);
        USB_driver.open(0x02);
        USB_driver.read(0x03);
        USB_driver.write(0x04);
        USB_driver.close(0x05);
        USB_driver.exit(0x06);
}
#endif

出现以下错误:

[user@localhost fn-ptr]$ emacs fn-ptr.c

(emacs:4983): Gtk-WARNING **: Allocating size to Emacs 0xdb4270 without calling gtk_widget_get_preferred_width/height(). How does the code know the size to allocate?
[user@localhost fn-ptr]$ gcc fn-ptr.c
fn-ptr.c:78:11: error: expected identifier or ‘(’ before ‘.’ token
 USB_driver.init = &USB_init;
           ^
fn-ptr.c:79:11: error: expected identifier or ‘(’ before ‘.’ token
 USB_driver.open = &USB_open;
           ^
fn-ptr.c:80:11: error: expected identifier or ‘(’ before ‘.’ token
 USB_driver.read  = &USB_read;
           ^
fn-ptr.c:81:11: error: expected identifier or ‘(’ before ‘.’ token
 USB_driver.write = &USB_write;
           ^
fn-ptr.c:82:11: error: expected identifier or ‘(’ before ‘.’ token
 USB_driver.close = &USB_close;
           ^
fn-ptr.c:83:11: error: expected identifier or ‘(’ before ‘.’ token
 USB_driver.exit  = &USB_exit;
           ^
[user@localhost fn-ptr]$ 

这里的问题是:我应该怎样做才能使这段代码工作,因为构建这段代码的下面的单个函数指针示例可以很好地工作:

typedef unsigned char uint8_t;
typedef void (*generic_func_t)(uint8_t);

generic_func_t init;

void USB_init(uint8_t x)
{
        /* here body of this f-n */
        printf("USB_open 0x%x\n", x);
}

init = &USB_init;

3 个答案:

答案 0 :(得分:1)

只需从USB_driver移除typedef struct,然后使用typedef struct driver_t USB_driver;中的代码进行初始化即可使main成为变量。

像这样:

driver_t USB_driver;

int main(void) {
    USB_driver.init = &USB_init;
    USB_driver.open = &USB_open;
    USB_driver.read  = &USB_read;
    USB_driver.write = &USB_write;
    USB_driver.close = &USB_close;
    USB_driver.exit  = &USB_exit;

    USB_driver.init(0x01);
    USB_driver.open(0x02);
    USB_driver.read(0x03);
    USB_driver.write(0x04);
    USB_driver.close(0x05);
    USB_driver.exit(0x06);

    return 0;
}

或者更好地制作新的创作功能:

void USB_Driver_create(driver_t *driver)
{
    driver->init = &USB_init;
    driver->open = &USB_open;
    driver->read  = &USB_read;
    driver->write = &USB_write;
    driver->close = &USB_close;
    driver->exit  = &USB_exit;
}

答案 1 :(得分:0)

首先,USB_driver类型,而不是变量。您需要首先使用此类型的变量来访问成员(例如,初始化成员的值)。

那说,初看起来似乎是

    USB_driver.init = &USB_init;
    USB_driver.open = &USB_open;
    USB_driver.read  = &USB_read;
    USB_driver.write = &USB_write;
    USB_driver.close = &USB_close;
    USB_driver.exit  = &USB_exit;

这些语句,赋值语句,驻留在文件范围内。这是不允许的。仅在块范围内允许分配操作(不同于初始化)。

你需要它们在块范围内,在某个函数main()内,可能。

答案 2 :(得分:-1)

您必须声明类型为USB_driver变量

void main(void) {
    USB_driver dr
    dr.init(0x01);
    dr.open(0x02);
    dr.read(0x03);
    dr.write(0x04);
    dr.close(0x05);
    dr.exit(0x06);
}

尝试使用