Home > other >  Store Pointers to Multiple Functions in Array
Store Pointers to Multiple Functions in Array

Time:01-14

I have some sample code that creates an array of pointers and stores the pointers to multiple functions in it (in this case, callback functions for an interrupt). This sample code builds in one compiler (gcc), and not in another(IAR). Just curious why it wouldn't work in one compiler. Is it potentially bad practice?

typedef void (*tc_channel_ptr)(uint32_t);
tc_channel_ptr tc0_channel_cb[TC_CHANNEL_COUNT];

void tc_register_callback(void *hw, uint8_t channel, void *cb)
{
    tc0_channel_cb[channel] = cb;
}

IAR gives an error: "a value of type "void*" cannot be assigned to an entity of type "tc_channel_ptr"

CodePudding user response:

IAR gives an error: "a value of type "void*" cannot be assigned to an entity of type "tc_channel_ptr"

IAR is justified in doing so. C permits void * to be converted to any other object pointer type, and such conversions are performed automatically by the assignment operator, but C does not make any provision for void * to be converted to function pointer types. The behavior of your assignment is therefore undefined.

GCC exercises an extension in accepting your code. It is within its rights to do so, but it is not valid to infer from its acceptance that the code is strictly conforming or that other compilers must accept it.

Bottom line: your callback registration function should specify the correct type for its third argument:

void tc_register_callback(void *hw, uint8_t channel, tc_channel_ptr cb)
{
    tc0_channel_cb[channel] = cb;
}

I don't see any advantage to declaring cb as a void * instead.


As a separate matter, I strongly agree with your other answer that you should not hide pointer nature behind a typedef. That is a matter of style, however, not code correctness. It is not related to the error you observe.

CodePudding user response:

I would not hide pointers (even the function pointers) behind the typedefs. If you do not, it is very easy to see if something is pointer or not.

typedef void tc_channel_func(uint32_t);
tc_channel_func *tc0_channel_cb[TC_CHANNEL_COUNT];

void tc_register_callback(void *hw, uint8_t channel, void *cb)
{
    tc0_channel_cb[channel] = (tc_channel_func *)cb;
}

or

void tc_register_callback(void *hw, uint8_t channel, tc_channel_func *cb)
{
    tc0_channel_cb[channel] = cb;
}

but the second version can move the problem to another part of the code.

  •  Tags:  
  • Related