【问题标题】:Understanding how to use typedef void function with pointers as params了解如何将 typedef void 函数与指针作为参数一起使用
【发布时间】:2021-02-05 05:00:39
【问题描述】:

我正在尝试了解一个用 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);呢?

【问题讨论】:

  • 因为const *dwt_cb_data_t 不是参数的有效声明?为什么你认为这应该等同于const dwt_cb_data_t*
  • typedef 从不定义变量,它们定义类型。你对参数的含义是正确的,但我很困惑为什么你认为const *dwt_cb_data_t 是合法的语法。指向T 的指针总是写成T* 而不是*T
  • @UnholySheep @john 我错过了变量类型是 const dwt_cb_data_t 而不仅仅是 const 的事实。现在把*放在最后是有意义的

标签: c++ c pointers typedef function-declaration


【解决方案1】:
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 
}

不带参数名更容易阅读。

【讨论】:

    【解决方案2】:

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

    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
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        是不是说函数的输入是函数的指针 结构?

        是的,表示函数的参数是一个指向结构体的指针。

        既然如此,为什么不写

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

        改为?

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

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

        唯一的一点是var被省略了。

        【讨论】:

        • 我错过了const dwt_cb_data_t 是实际类型并且省略了变量;现在它更有意义了
        【解决方案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 *);
        

        这很清楚。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-03
          • 1970-01-01
          • 2019-05-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多