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

Nic*_*ldo 2 c c++ pointers typedef function-declaration

我试图理解用 C 编写的固件,它驱动超宽带连接的芯片。

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

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

typedef struct
{
   //some data
   dwt_cb_t    cbTxDone; // Callback for TX confirmation event
   //some other data
} dwt_local_data_t ;
Run Code Online (Sandbox Code Playgroud)

我知道该结构名为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 *);
Run Code Online (Sandbox Code Playgroud)

其中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;
Run Code Online (Sandbox Code Playgroud)

现在,我试图理解 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);

bol*_*lov 5

停止思考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 *);
Run Code Online (Sandbox Code Playgroud)

这是非常清楚的。


Vla*_*cow 4

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

void f( int *x );
Run Code Online (Sandbox Code Playgroud)

函数的类型是void( int * ).

您可以为此函数类型引入别名,例如

typedef void Func( int * );
Run Code Online (Sandbox Code Playgroud)

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

这是一个演示程序。

#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;
}
Run Code Online (Sandbox Code Playgroud)

程序输出是

x = 0
x = 1
Run Code Online (Sandbox Code Playgroud)

请注意,您还可以通过以下方式声明函数别名

void typedef Func( int * );
Run Code Online (Sandbox Code Playgroud)

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

你可以简单地写

typedef void Func( int * );
Run Code Online (Sandbox Code Playgroud)

typedef Func *FuncPtr;
Run Code Online (Sandbox Code Playgroud)

这是一个演示程序。

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

#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;
}
Run Code Online (Sandbox Code Playgroud)

现在比较这些别名声明

typedef void ( *FuncPtr )( int * );
typedef void (*dwt_cb_t)(const dwt_cb_data_t *);
Run Code Online (Sandbox Code Playgroud)

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

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

using dwt_cb_t = void (*)(const dwt_cb_data_t *);
Run Code Online (Sandbox Code Playgroud)

在 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;
}
Run Code Online (Sandbox Code Playgroud)

程序输出是

x = 1
c = B
Run Code Online (Sandbox Code Playgroud)