【问题标题】:What is (void (**) ()) and how to typedef it?什么是 (void (**) ()) 以及如何 typedef 它?
【发布时间】:2013-04-29 10:37:25
【问题描述】:

在我必须理解的嵌入式代码中,有这行代码:

*((void (**) ()) 0x01) = c_int01; /* Write the interrupt routine entry */

我可以理解您使用函数指针c_int01 设置中断向量的事实,但我不知道(void (**) ()) 指的是哪种类型的转换。我知道标准函数指针符号(void (*)()),但不知道另一个。

我尝试重构代码,使其看起来更具可读性,如下所示:

// header
typedef void (*interrupt_handler)(); // prototype of an interruption handler
#define INTERRUPT_VECTOR 0x01
#define SET_INTERRUPT_HANDLER( handler ) *((interrupt_handler) INTERRUPT_VECTOR) = (handler)

// code
SET_INTERRUPT_HANDLER( c_int01 );

但是嵌入式编译器抱怨 LHS 不是一个对象。

有人知道这个符号是什么意思吗? (void (**)())

// 编辑:

对于那些感兴趣的人,我会更好地理解这一点:

*( (void (*)())* 0x01) = c_int01;

【问题讨论】:

  • 它是一个指向函数指针的指针。
  • MAAANNN,我怎么没看到……我明白了。
  • 除非您的平台有sizeof(void(*)()) == 1 或向量表从奇数地址开始,否则0x01 不可能是正确的。
  • 我确认,sizeof(char) == sizeof(int) == 1 == 32bits 在我的平台上(嵌入式 DSP)。

标签: c function-pointers typedef interrupt


【解决方案1】:

这是一个指向函数的指针。

因此,强制转换将整数 0x01 转换为类型为 (void (*)()) 的函数指针的地址

你可以重写它:

typedef void (*interrupt_handler)();
*((interrupt_handler*) 0x01) = c_int101;

【讨论】:

  • 这样更易读。 ** 似乎有些矫枉过正,而 (void (*)() )* 则清晰得多。
【解决方案2】:

(void (**) ()) 是一个指向函数指针的指针。

(void (*)()) 是指向函数的指针,因此添加星号会增加一层间接性。)

你需要说:

*((interrupt_handler*) INTERRUPT_VECTOR) = (handler)

其内容为,“将INTERRUPT_VECTOR 视为指向函数指针的指针,并将其值设置为handler。”

【讨论】:

  • 知道了,史蒂夫是第一个回答的,所以我会得到他的回答。你的得到我的支持。
【解决方案3】:

下面是永远有用的cdecl 对那个表达式的核心(void (**) ()) 所说的话:

将 unknown_name 转换为指向返回 void 的函数的指针

所以,它是一个强制类型转换(由外面的一对括号表示),类型是“指向函数的指针”,这似乎是有道理的。

【讨论】:

    【解决方案4】:

    Cdecl 将是更快的了解方式:

         cast unknown_name into pointer to pointer to function returning void
    

    著名的“螺旋规则将是下一个:

              +-----+
              |+-+  |
              || |  V
       (void (** |)( ))
          ^   ^^||  |
          |   ||||  |
          |   ||+|  |
          |   +--+  |
          +---------+
    

    按照您阅读的内容:

    • 指向的指针
    • 指向的指针
    • 一个函数返回
    • 无效

    【讨论】:

    • 你必须告诉我更多关于你的螺旋规则!
    • @xgbi:不要太担心spiral rule
    • 我多年前从一本杂志(计算机杂志,适合那些老得记得它的人)了解到它也在 comp.lang.c 常见问题解答中:c-faq.com/decl/spiral.anderson.html
    【解决方案5】:

    您可以将中断入口点向量的设置可视化为

       void (*interupt_handlers)()[256] = 0;
    
       void set_interupt_handler(int vector, void(*handler)())
       {
           interupt_handlers[vector] = handler;
       }
    

    【讨论】:

      猜你喜欢
      • 2014-03-30
      • 2012-07-22
      • 2014-11-15
      • 2011-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多