5

In an embedded code I have to understand, there's this line of code :

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

I can grasp the fact that you setup the interruption vector with the function pointer c_int01, but I can't figure what kind of cast (void (**) ()) refers to. I know the standard function pointer notation (void (*)()) but not the other one.

I tried to refactor the code so that it looked a bit more readable like this:

// 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 );

But the embedded compiler whines about the LHS not beeing an object.

Anybody know what this notation signifies? (void (**)())

// EDIT:

For those interrested, I would understand this much better:

*( (void (*)())* 0x01) = c_int01;
Gui13
  • 12,993
  • 17
  • 57
  • 104

5 Answers5

11

It's a pointer-to-pointer-to-function.

So the cast converts the integer 0x01 to the address of a function pointer having type (void (*)())

You could rewrite it:

typedef void (*interrupt_handler)();
*((interrupt_handler*) 0x01) = c_int101;
Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • This is way more readable. `**` seems overkill, whereas `(void (*)() )*` is much much clearer. – Gui13 Apr 29 '13 at 12:12
5

(void (**) ()) is a pointer to a function pointer.

((void (*)()) is a pointer to a function, so adding a star adds a level of indirection.)

You need to say:

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

That reads, "Treat INTERRUPT_VECTOR as a pointer to a function pointer, and set its value to handler."

RichieHindle
  • 272,464
  • 47
  • 358
  • 399
2

Here's what the ever-useful cdecl says about the core of that expression, the (void (**) ()):

cast unknown_name into pointer to pointer to function returning void

So, it's a cast (as signified by the outer pair of parentheses), and the type is "pointer to pointer to function", which seems to make sense.

unwind
  • 391,730
  • 64
  • 469
  • 606
1

Cdecl would be the quicker way to know:

     cast unknown_name into pointer to pointer to function returning void

The famous "spiral rule would be the next:

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

Following the lines you read:

  • a pointer to
  • a pointer to
  • a function returning
  • void
Remo.D
  • 16,122
  • 6
  • 43
  • 74
  • You have to tell me more about this spiral rule of yours! – Gui13 Apr 29 '13 at 10:51
  • 1
    @xgbi: Don't worry too much about the [spiral rule](http://stackoverflow.com/questions/16260417/the-spiral-rule-about-declarations-when-is-it-in-error) – CB Bailey Apr 29 '13 at 11:00
  • I've learned it many years ago from a magazine (Computer Magazine for the ones old enough to remember it) it's also in the comp.lang.c FAQ: http://c-faq.com/decl/spiral.anderson.html – Remo.D Apr 29 '13 at 11:40
-1

You may visualize the setting of interrupt entry point vector as

   void (*interupt_handlers)()[256] = 0;

   void set_interupt_handler(int vector, void(*handler)())
   {
       interupt_handlers[vector] = handler;
   }
V-X
  • 2,979
  • 18
  • 28