了解如何使用指针作为参数的 typedef void 函数

Understanding how to use typedef void function with pointers as params

我正在尝试了解一个用 C 编写的固件,该固件驱动用于超宽带连接的芯片。

固件大量使用 typedef 和指针。我已经理解固件背后的大部分想法,但有一个 typedef void 函数我无法理解。

基本上,固件会创建一个结构来保存设备数据

typedef struct
{
   //some data
   dwt_cb_t    cbTxDone; // Callback for TX confirmation event
   //some other data
} dwt_local_data_t ;

我了解到该结构名为 dwt_local_data_t 并包含一些变量,包括这个奇怪的 dwt_cb_t类型。

在.h文件中dwt_cb_t命名为

// Call-back type for all events    
typedef void (*dwt_cb_t)(const dwt_cb_data_t *);

其中dwt_cb_data_t

形式的另一种结构
typedef struct
{
    uint32 status;      //initial value of register as ISR is entered
    uint16 datalength;  //length of frame
    uint8  fctrl[2];    //frame control bytes
    uint8  rx_flags;    //RX frame flags, see above
} dwt_cb_data_t;

现在,我正在尝试理解 typedef void (*dwt_cb_t)(const dwt_cb_data_t *);

的含义

据我了解,typedef void 是指向函数的指针类型。它定义了一个变量 dwt_cb_t 指向一个接收常量结构 dwt_cb_data_t[=19= 作为输入的函数]

我不知道我的推理是否正确,因为我不明白为什么dwt_cb_data_t的末尾有一个*。是不是说函数的输入就是结构体的指针呢?在这种情况下,为什么不写 typedef void (*dwt_cb_t)(const *dwt_cb_data_t); 呢?

别再考虑 typedef void 了。您正在以这种方式截断定义。

定义的符号是 dwt_cb_t 并且是类型 void (*)(const dwt_cb_data_t *) 的别名,它是:指向采用 const dwt_cb_data_t * 参数并返回 void 的函数的指针。

在 C++ 中你会这样写:

using dwt_cb_t = void (*)(const dwt_cb_data_t *);

这就清楚多了。

Does it mean that the input of the function is the pointer of the structure?

是的,说明函数的参数是指向struct的指针。

In this case, why don't write

typedef void (*dwt_cb_t)(const*dwt_cb_data_t);

instead?

这是因为指针符号*必须放在标识符之前,而不是标识符类型之前。 在这种情况下,您可以看到函数如下:

typedef void (*dwt_cb_t)(const dwt_cb_data_t *var);

唯一就是省略了var

Now, I'm trying to understand the meaning of typedef void (*dwt_cb_t)(const dwt_cb_data_t *);

typedef void (*dwt_cb_t)(const dwt_cb_data_t *);

意味着,定义一个类型dwt_cb_t,它是一个指向returnsvoid函数的指针,并接受一个const dwt_cb_data_t *.

类型的参数

如果你有一个功能,比如

 void func(const dwt_cb_data_t * data); // func accepts argument type 
                                           const dwt_cb_data_t * , returns void 

你可以写

 dwt_cb_t f = func;

为了更清楚,我们假设有一个函数声明为

void f( int *x );

函数的类型是void( int * )

你可以为这个函数类型引入一个别名,比如

typedef void Func( int * );

并使用别名声明(但不定义)函数

这是一个演示程序。

#include <stdio.h>

typedef void Func( int * );

Func f;

int main(void) 
{
    int x = 0;
    
    printf( "x = %d\n", x );
    
    f( &x );

    printf( "x = %d\n", x );
    
    return 0;
}

void f( int *x )
{
    ++*x;
}

程序输出为

x = 0
x = 1

注意你也可以通过以下方式声明函数别名

void typedef Func( int * );

现在让我们为指向函数类型的函数指针声明一个别名。

你可以简单地写

typedef void Func( int * );

typedef Func *FuncPtr;

这是一个演示程序。

#include <stdio.h>

typedef void Func( int * );

Func f;

typedef Func *FuncPtr;

int main(void) 
{
    int x = 0;
    
    printf( "x = %d\n", x );
    
    FuncPtr fp = f;

    fp( &x );

    printf( "x = %d\n", x );
    
    return 0;
}

void f( int *x )
{
    ++*x;
}

另一方面,您可以为指向函数类型的指针声明别名,而无需使用函数类型的别名。

#include <stdio.h>

typedef void Func( int * );

Func f;

typedef void ( *FuncPtr )( int * );

int main(void) 
{
    int x = 0;
    
    printf( "x = %d\n", x );
    
    FuncPtr fp = f;

    fp( &x );

    printf( "x = %d\n", x );
    
    return 0;
}

void f( int *x )
{
    ++*x;
}

现在比较这些别名声明

typedef void ( *FuncPtr )( int * );
typedef void (*dwt_cb_t)(const dwt_cb_data_t *);

唯一的区别是参数的类型。在第一个声明中参数的类型是 int * 而在第二个声明中参数的类型是 const dwt_cb_data_t *.

在 C++ 中,您可以将 using 声明与 typedef(s) 一起使用,例如

using dwt_cb_t = void (*)(const dwt_cb_data_t *);

在 C++ 中使用别名声明更加灵活,因为您可以使用模板别名声明。

这是一个演示程序。

#include <iostream>

template <typename T>
using FuncPtr = void ( * )( T * );

template <typename T>
void f( T *t )
{
    ++*t;
}

int main() 
{
    FuncPtr<int>  fp1 = f;
    FuncPtr<char> fp2 = f;
    
    int x = 0;
    char c = 'A';
    
    fp1( &x );
    fp2( &c );
    
    std::cout << "x = " << x << '\n';
    std::cout << "c = " << c << '\n';
    
    return 0;
}

程序输出为

x = 1
c = B
typedef void (*dwt_cb_t)(const dwt_cb_data_t *);

这只是意味着 dwt_cb_data_t 是一种数据类型,而 dwt_cb_data_t * 只不过是指向它的指针。

函数原型只是缺少它的正式参数名称,这很好。 这个的降级版本是:

int myFunc(int, char*);  // no formal parameter name, just its datatype

稍后,在它的实现中,您会看到

int myFunc(int var1, char* var_ptr){
//function body 
}

只是没有参数名更容易阅读。