将整数转换为函数指针

时间:2018-02-04 06:07:20

标签: c pointers function-pointers

我试图将一个整数转换为函数指针。基本上我的整数值包含函数指针的地址,所以我试图把它转换成它。

我正在尝试执行以下操作 -

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

我正在调用function3,其参数包含function1的地址。当我运行程序时,我收到以下警告 -

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

我有什么方法可以处理这个警告吗?

3 个答案:

答案 0 :(得分:3)

  

将整数转换为函数指针
  “我希望让它与系统无关”

这不是100%可能,因为C没有指定一个可以保存所有orignal 函数指针的整数类型。

  

整数可以转换为任何指针类型。除非先前指定,否则结果是实现定义的,可能未正确对齐,可能不指向引用类型的实体,并且可能是陷阱表示。 C11dr§6.3.2.3 5

走另一条路:

  

任何指针类型都可以转换为整数类型。除了之前指定的以外,结果是实现定义的。 如果结果无法以整数类型表示,则行为未定义。结果不必位于任何整数类型的值范围内。 §6.3.2.3 6

示例:函数指针为128位,最宽整数类型为64位。

代码可以尝试使用最宽的整数类型,如(u)intmax_t。虽然这确实很有成功的机会,但在某些平台上它仍然可能太小。

可选的整数类型(如(u)intptr_t)可以往返void * 对象指针函数指针可能比void *宽,因此这种方法不足以用于独立于系统的解决方案。

答案 1 :(得分:2)

不要养成尝试将整数类型转换为指针的习惯。这不是传递某事物地址的正确方法 - 这就是为什么存在指针类型的原因。 (是的,你可以用无符号类型表示一个指针,条件是无符号类型与指针大小相同,但不要使用指针需要指针)

function3的示例中,您要从其中调用function2。由于function2需要将func_ptr类型作为参数,function3的参数列表中应该包含func_ptr类型的参数,以便您可以将其传递给function2内。 (除非你在全局范围内定义了func_ptr - 但除非绝对需要,否则应该避免 - 例如回调,这里不相关,在学习C时很少见到)

将您的作品组合在一起的简短示例可能有所帮助。这样可以使用函数定义和typedef为function3提供适当的参数,它可以在调用function2时使用它,例如

#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;
}

示例使用/输出

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

仔细看看,如果您有其他问题,请告诉我。

答案 2 :(得分:1)

C标准不允许将void *转换为指向某个函数的指针,也不允许再转回 - void *的措辞位于6.3.2.3p1

  

指向void的指针可以转换为指向任何对象类型的指针。指向任何对象类型的指针可以转换为指向void的指针,然后再返回;结果应该等于原始指针。

但是,函数不是对象,因此您甚至无法移植到void *的函数指针。

现在,据说可以将指针转换为整数,然后再返回:

  

6任何指针类型都可以转换为整数类型。除了之前指定的以外,结果是实现定义的。 如果结果无法以整数类型表示,则行为未定义。结果不必位于任何整数类型的值范围内。

如果您的(函数)指针是64位且int 32位,则行为未定义。对于指向对象的指针,您可以使用(u)intptr_t - 但这不能保证与函数指针一起使用。相反,对于函数指针,可以保证可以将任何函数指针转换为另一个,因此可以使用generic function pointer,例如

typedef void (*funcptr)(void);

并在调用之前将其转换为正确的函数指针类型。

如果您还需要整数,则必须使用联合

union int_or_funcptr {
    int integer;
    funcptr function;
}

如果需要该函数,请分配或读取union的function成员,在调用它之前正确地进行转换。