[英]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作為輸入
我不知道我的推理是否正確,因為我不明白為什么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 *);
這是非常清楚的。
為了更清楚,讓我們假設有一個函數聲明如下
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++ 和 typedef(s) 中,您可以使用 using 聲明,例如
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);
反而?
這是因為指針符號*
必須放在標識符之前,而不是標識符的類型之前。 在這種情況下,您可以看到函數如下:
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;
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
}
沒有參數名稱更容易閱讀。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.