【问题标题】:Why cast pointer to function为什么将指针转换为函数
【发布时间】:2015-03-26 01:50:36
【问题描述】:

我一直在研究一些代码,遇到了一些我理解的代码,但我想不出为什么会这样。

我在下面的代码中重现了这种情况:

include <stdio.h>

void printsum(int x, double y)
{
     printf("Soma: %.2f\n", (double)x + y);
}

typedef int int_alias;

typedef void (* funcptr) (int_alias x, double y);
typedef void (* fptr) (int x, double y);

fptr pptr = &printsum;

#define A_MACRO(x, y) ((funcptr) (pptr)) (x, y)

int main()
{
    int a = 10;
    double b = 2.2;

    A_MACRO(a, b);
    /* ((funcptr) (pptr)) (a, b); */

    return 0;
}

这是在事件发生并调用宏时完成的,因此打印函数是一个回调函数。

我不明白的是由于宏而发生的转换,据我所知pptr 已经是一个指向函数的指针,那么为什么要再次转换为funcptr 呢?

我对这种结构不是很熟悉,所以也许是我缺少的东西,谁能给我一些关于这个的信息?

【问题讨论】:

  • 我认为没有这个转换结果会是一样的。
  • 这看起来很奇怪...你能分享原始代码的链接吗?
  • 即使#define A_MACRO(x, y) (pptr)(x, y) 也可以。无需铸造。可能在这种情况下这样做是为了提高代码的可读性。
  • @mafso 不是真的,这是很多代码,不是我的...
  • 要给出有用的答案,我们可能需要更多信息。 (顺便说一句,你认识作者吗?)代码是从一开始就这样写的吗? (这样的事情可能是合并代码的结果。)我很想标记这个问题,没有代码很难以问答形式回答,讨论板可能更合适。

标签: c casting callback function-pointers


【解决方案1】:

funcptrfptr 都是函数指针的别名,是的,但它们可能是指向函数的指针具有不同的参数类型,具体取决于 int_alias 的定义。

如果int_alias 的类型定义不是int(或等效的signed int),则强制转换是危险的。无论如何,指针值都会被强制转换保留,但通过强制转换指针调用函数,就像A_MACRO() 所做的那样,在这种情况下会产生未定义的行为。

请注意,“int 以外的任何内容”都包括枚举类型。虽然枚举类型的值可以隐式转换为int,但枚举类型不是int。这是与真正实质的区别,因为实现可能使用比int 更窄的枚举类型的表示。例如,GCC 可能会根据其值范围和编译器选项为各种枚举类型选择宽度和符号不同的表示。

综上所述,A_MACRO() 的演员阵容虽然本身合法,但没有任何用处。它实际上可能是有害的。最初编写它的人可能希望它帮助使代码适应不同的整数类型(通过int_alias typedef),但实际上这是一个等待发生的错误。更好的选择是这个......

#define A_MACRO(x, y) ((pptr) ((int) x, y))

...或者干脆...

#define A_MACRO(x, y) ((pptr) (x, y))

...如果重点是隐藏函数是通过指针调用的事实。

【讨论】:

  • gcc 默认使用unsigned int(或int,如果有负常数)enum(编译C时,不确定C++),并且只有(unsigned) char/short-fshort-enums。 (可能有些目标有不同的默认值。)
  • @mafso,谢谢,我相应地修改了我的 cmets。我在制作原始 cmets 时查看了错误的文档。
猜你喜欢
  • 1970-01-01
  • 2014-10-22
  • 2012-11-21
  • 2020-12-10
  • 1970-01-01
  • 2016-08-07
  • 1970-01-01
  • 1970-01-01
  • 2016-06-03
相关资源
最近更新 更多