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

问题描述

我试图了解用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

作为输入。

我不知道我的推理是否正确,因为我不明白为什么 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 *);

这很清楚。

,

是否表示该函数的输入是该函数的指针 结构?

是的,它表示函数的参数是指向该结构的指针。

在这种情况下,为什么不写

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

相反?

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

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

唯一的是省略了var

,

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

的含义。
typedef void (*dwt_cb_t)(const dwt_cb_data_t *);

是指定义类型dwt_cb_t,该类型是指向返回void并接受类型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 );
    
    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 ++中,您可以使用typedef作为声明

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 
}

不用参数名就更容易阅读。