简体   繁体   中英

Cast integer to function pointer

I am trying to cast an integer to a function pointer. Basically my integer value contains the address of the function pointer, so I am trying to cast it into it.

I am trying to do the following-

typedef void (*func_ptr)(unsigned int arg1);

void function1(unsigned int argument)
{
}

void function2(unsigned int argument, func_ptr argument2)
{
    /* Do something here*/
}

void function3(unsigned int argument)
{
    function2(123,(func_ptr)argument);
}

I am calling function3, whose argument contains the address of function1. When I run the program, I get the following warning-

cast to pointer from integer of different size [-Wint-to-pointer-cast]

Is there any way I can deal with this warning?

Cast integer to function pointer
"I wish to make it system independant"

This is not 100% possible because C does not specify an integer type that can certainly hold all of the orignal function pointer .

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation. C11dr § 6.3.2.3 5

Going the other way:

Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type. § 6.3.2.3 6

Example: function pointers are 128 bit and the widest integer type is 64 bit.

Code can attempt using the widest integer types like (u)intmax_t . Although that does have a high chance of success, it still may be too small on select platforms.


Optional integer types like (u)intptr_t can round trip a void * object pointer though. A function pointer may be wider than a void * , so this approach is insufficient for a system independent solution.

Do not get in the habit of trying to cast integer types to pointers. That isn't the proper way to pass the address of something -- that's why there is pointer types. (yes, you can represent a pointer with an unsigned type provided the unsigned type is the same size as a pointer, but don't, instead use a pointer where a pointer is required)

In your example of function3 you want to call function2 from within it. Since function2 requires as a parameter a type func_ptr , function3 should have a parameter of func_ptr type in its parameter list so that you can pass it to function2 within. (unless you have a func_ptr defined globally -- but that should be avoided as well unless absolutely required -- such as a callback, not relevant here and rarely seen when learning C)

A short example putting your pieces together may help. This makes use of your function definitions and typedef to provide a proper argument to function3 which it can utilize in its call to function2 , eg

#include <stdio.h>

typedef void (*func_ptr)(unsigned int arg1);

void function1(unsigned int argument)
{
    printf ("my dog has %u fleas.\n", argument); 
}

void function2 (unsigned int argument, func_ptr argument2)
{
    printf ("my cat has %u fleas.\n", argument);
    argument2 (argument); 
}

void function3(func_ptr argument)
{
    function2 (123, argument);
}

int main (void) {

    function2 (4, function1);
    function3 (function1);

    return 0;
}

Example Use/Output

$ ./bin/fncptr
my cat has 4 fleas.
my dog has 4 fleas.
my cat has 123 fleas.
my dog has 123 fleas.

Look things over and let me know if you have further questions.

The C standard doesn't allow casting even void * to a pointer to a function or back again - the wording for void * is in 6.3.2.3p1 :

A pointer to void may be converted to or from a pointer to any object type . A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.

However, functions are not objects so you cannot even cast a function pointer to void * portably.

Now, it is said that a pointer can be converted to an integer, and back again, though:

6 Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

If your (function) pointers are say 64 bits and int 32 bits, the behaviour is undefined. For pointers to objects you can use (u)intptr_t - but this is not guaranteed to work with function pointers. Instead for function pointers it is guaranteed that you can cast any function pointer to another, so you can use a generic function pointer , for example

typedef void (*funcptr)(void);

and cast this to the proper function-pointer-type before calling.


If you need an integer too, then you must use an union

union int_or_funcptr {
    int integer;
    funcptr function;
}

and if the function is needed, assign or read the function member of the union, casting it properly prior to calling it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM