在结构定义内的函数指针内使用 void* 作为参数会导致语法错误

Using a void* as an argument inside a function pointer inside a structure definition causes a syntax error

我正在创建一个界面结构

typedef struct Circular_Buffer_Interface_t * Circular_Buffer_Interface;
typedef struct Circular_Buffer_Interface_t {
    U8 (*Put)(Circular_Buffer, void*);
    U8 (*Get)(Circular_Buffer, void*);
    U8 (*Reset)(Circular_Buffer);
    BOOL (*isFull)(Circular_Buffer);
    BOOL (*isEmpty)(Circular_Buffer);
} Circular_Buffer_Interface_t;

typedef struct Circular_Buffer_t * Circular_Buffer;
typedef struct Circular_Buffer_t {
    Circular_Buffer_Interface Interface;
} Circular_Buffer_t;

我的问题是当我尝试编译时为什么使用 void* 作为函数参数会引发语法错误。

如果我使用 typedef typedef void* VoidPtr

然后使用

typedef void* VoidPtr;
typedef struct Circular_Buffer_Interface_t {
    U8 (*Put)(Circular_Buffer, VoidPtr);
    U8 (*Get)(Circular_Buffer, VoidPtr);
    U8 (*Reset)(Circular_Buffer);
    BOOL (*isFull)(Circular_Buffer);
    BOOL (*isEmpty)(Circular_Buffer);
} Circular_Buffer_Interface_t;

一切正常。

有人知道发生这种情况的线索吗? 提前致谢。

带有 void * 的第一个声明似乎完全有效 C。我添加了一些代码以使其成为一个完整的程序:

#include <stdio.h>

typedef int U8;
typedef int BOOL;
typedef int Circular_Buffer;

typedef struct Circular_Buffer_Interface_t {
    U8 (*Put)(Circular_Buffer, void*);
    U8 (*Get)(Circular_Buffer, void*);
    U8 (*Reset)(Circular_Buffer);
    BOOL (*isFull)(Circular_Buffer);
    BOOL (*isEmpty)(Circular_Buffer);
} Circular_Buffer_Interface_t;

int main() {
    puts("hello");
}

此程序在 MacOSX 上使用 GNU C 5.2 版编译成功且没有警告:

> gcc-5 -std=c99 -Wall x.c
> ./a.out
hello

同样适用于 Apple 版本的 clang。因此,我怀疑问题出在您的 C 编译器上,而不是您的代码上。

本次会员声明

U8 (*Put)(Circular_Buffer, VoidPtr);
如果 Circular_BufferVoidPtr 都没有在源代码中用 typedef 定义,

将正常工作。 (但必须定义 U8。)这是因为它将被接受为 K&R 风格的函数声明,它指定参数的名称而不是它们的类型。 (也就是说,Put 将被声明为一个指向带有两个未指定类型参数的函数的指针。)

如果 Circular_BufferVoidPtr 都定义为 typedef,它也可以工作,在这种情况下,它将被视为普通的标准 C 声明。

如果使用-Wall编译,第一种情况可能会产生警告。 -Wall 总是 推荐。

如果两个标识符中只有一个被声明为typedef,它应该会编译失败,所以我不知道在成员声明之前出现typedef void* VoidPtr的情况下它是如何工作的, typedef struct ... Circular_Buffer 紧随其后。也许这是旧版本 gcc 的一个模糊特性。 (一旦编译器确定它是一个 K&R 函数声明,实际的参数名称可以被忽略,除非它是一个函数定义,并且在该行出现的上下文中,它不能是一个函数定义。)