0

I'm writing code for an embedded system. The compiler is a GCC derivative. Is the following code correct?

void *voidPointer = 0;
int (*functionPointer)(int a);

int testFunction(int a)
{
   return(a+1);
}

void registerFunction(void *pvFunctionAddress)
{
   voidPointer = pvFunctionAddress;
}

main()
{
   ...
   registerFunction(testFunction);
   functionPointer = voidPointer;
   x = functionPointer(17);
   ...
}

Now x should have the value 18. The compiler does not show an error - but is this correct? Or do we overwrite some memory on the stack.

Thanks.

3 Answers3

3

No, it can never be "correct" since strictly speaking C forbids conversions between void * and function pointers.

If it works, it's because a particular compiler allows it for that particular target (operating system + hardware combination).

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

Strictly speaking, according to the C standard, a void* is not guaranteed to be able to hold a function pointer. I believe that POSIX does require that a function pointer be able to be stored in a void* (in order to support the dlsym() function). See https://stackoverflow.com/a/12359083/12711

Community
  • 1
  • 1
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
0

Let's say it like this:

In C a function is identified by the address of the first instruction in the appropriate assembly that begins it's execution and it's calling convention, thus a void* is a valid storage class to store it if the calling convention is a compile-time constant. For most commonly used CPU architectures it is.

If your code works with your compiler for your target hardware then it it correct in that sense.

Here is a simple comparison:

uintptr_t i = NULL;

is valid C because uintptr_t (normally unsigned long int) is the same storage class as void * (type of NULL).

Sergey L.
  • 21,822
  • 5
  • 49
  • 75
  • OK - I understand - But is there a difference if the function return value is void or e.g. int? And do the function parameters influence the storage class? – user1839295 Nov 20 '12 at 16:10
  • You only said you are working on an embedded system, you did not specify a CPU architecture, so I cannot tell you that for your architecture. For x86 for example return values are generally passed in the `*ax` register and parameters (depending on the amount) are passed in registers or on the stack, but the compiler knows that from the function type. If the function does not return anything then the compiler will ignore `*ax` when it returns. As such in x86 the calling convention is compile-time constant and `void*` is a valid storage class. – Sergey L. Nov 20 '12 at 16:25