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);
停止思考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)
这是非常清楚的。
为了更清楚地说明,我们假设有一个函数声明如下
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)