Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Pointer to function conversions (11.1)

rule 11.1 disallows conversions between function pointers and any other type than integral type.

1. conversion between compatible function types - are they allowed? For example:
typedef struct S1 { int x; } TS1;
struct S1 (*f1)();
TS1 (*f2)();
f1 = f2; // Is this compliant?

2. what about following case?

    typedef int (*func_t)(char *);
    typedef STYPE_LIST (*func_t2)(char *);

    void moo() {
        func_t p;
        func_t2 p2;
        p= (func_t)p2;  // Is this compliant? Enum vs int
Question 1:
When compatible types are assigned, as in this first example, no "conversion" takes place. Therefore, Rule 11.1 is not relevant to this assignment.

Question 2:
The C language treats each enumerated type as compatible with an integer type. The choice of integer type is implementation-defined.

If the type chosen by the implementation for enum STYPE_LIST is compatible with int32_t then p and p2 have compatible types. The type cast is not required, no conversion takes place and Rule 11.1 is not relevant.

However, if the type chosen by the implementation for enum STYPE_LIST is not compatible with int32_t then p and p2 do not have compatible types. The type cast then violates Rule 11.1.
Posted by and on behalf of the MISRA C Working Group
What about the cast between function pointers with the same return type but different argument lists?
This is not a real conversion either, but sometimes necessary to get rid of compiler warnings.
When a pointer to a function type T1 is converted to a pointer to function type T2, many implementations will leave the value of the pointer unchanged. However, if the types T1 and T2 are not compatible, the C standard says that a call made using the converted pointer (pointer to T2) will give rise to undefined behaviour. Rule 11.1 limits the possibility for this undefined behaviour by preventing a direct conversion between incompatible function pointer types.

As an example of the kind of undefined behaviour that can arise, consider two functions with identical return types but different numbers and/or types of parameters. Suppose that the called function with type T1 requires 8 bytes for its parameters but T2 requires 6 bytes. A call is made to a function with type T1 using a pointer to type T2. The behaviour that results will depend on the way function calls are implemented in the particular compiler. Suppose that the caller pushes arguments onto the stack and then makes a call which then pushes a 2-byte return address onto the stack. The called function is expecting 8 bytes of parameters so it will access those parameters at the wrong stack offsets. When it returns it may use a return instruction that also adjusts the stack pointer to remove the arguments that were stacked by the caller, after loading the return address into the program counter. It will remove 8 bytes of argument from the stack which will result in the original calling function operating with its stack pointer 2 bytes below its location prior to the call sequence start. All of this can give rise to undefined behaviour such as incorrect results, exceptions and program crashes.
Posted by and on behalf of the MISRA C Working Group

Forum Jump:

Users browsing this thread: 1 Guest(s)