void*函数指针数组强制转换

4

我有一个数组,长这样:

void* functions[]; // pointer to functions, each function returns an int and has int parameters A and B

我想将这个转化为以下内容:

int (*F)(int a, int b) = ((CAST HERE) functions)[0];
int result = F(a, b);

我已经尝试使用“(int (*)(int, int))”作为转换,但编译器抱怨我正在尝试将函数指针用作数组。

编译器是正确的。检查一下你的括号。 - Ilja Everilä
1
可以尝试使用以下代码:int (*F)(int, int) = (int (*)(int,int))functions[0]; - Support Ukraine
1
Use a typedef... - n. m.
很遗憾,我无法 @M.M - Jas
3个回答

4

为函数类型使用typedef有助于简化代码:

typedef int F_type(int, int);

然后您可以编写以下内容:
F_type *F = (F_type *)(functions[0]);

在使用索引运算符之前,尝试将函数转换为其他内容会导致未定义的行为(严格别名违规)。

请注意,将void *转换为函数指针不受标准C支持。如果可能,请首先将数组设置为函数指针:

F_type *functions[] = { &func1, &func2 };

注意:有些人更喜欢使用typedef来定义函数指针类型,而不是直接使用函数类型。我认为避免使用指针typedef可以使代码更易读,但我提到这一点是为了让你能理解其他建议。


@gsamaras 当然。我对你的答案进行了投票,因为它会导致未定义的行为。另外,你声称 OP 不需要 typedef 的依据是什么? - M.M
哦,真的吗?嗯,我不确定为什么,请你能解释一下吗?啊,我可能错了,因为nm告诉OP关于typedef,然后OP回答说他不能这样做,但他是在回答mm..对不起! - gsamaras
3
感谢您采用更安全的方法,@M.M,非常感谢您,但问题是我在使用第三方库时想保持简单。因此,我确实避免使用typedefs。 - Jas
@M.M 谢谢,我更新了我的答案。现在看起来怎么样? :D - gsamaras
@Jas 我会说使用typedef比不使用更简单。 - M.M
显示剩余3条评论

2
使用(int (**)(int, int))进行转换可能看起来可以解决问题,但这会导致未定义的行为
void*转换为函数指针不是标准C语言。
请注意,将void*别名到其他类型是严格别名违规。在What is the effect of casting a function pointer void?中了解更多信息。
请考虑从一开始就使用函数指针数组。

2
别名和转换是两回事。别名不兼容的类型违反了严格别名规则,它不会调用转换。为了更明显地说明这一点,可以将 double d[2] = {5.0,6.0}; int x = d[0];(转换)与 int y = ((int *)&d)[0];(别名)进行比较。 - M.M

0

function 是一个指向类型为 void 的数据的指针数组。您想将其转换为指向类型为 int (*)(int, int) 的指针的指针,即 int (**)(int, int),因此以下操作可行:

int (*F)(int, int) = ((int (**)(int, int)) functions)[0];

正如@M.M所指出的,上面的代码将导致未定义行为。您可能需要阅读thisthis了解更多相关信息。
理想情况下,您会这样做:
// Array of 2 pointers to functions that return int and takes 2 ints
int (*functions[2])(int, int) = {&foo, &bar};

// a pointer to function
int (*F)(int, int) = functions[0];
int r = F(3, 4);

1
这会导致未定义的行为。 - M.M
我测试了一下,似乎对我的应用程序有效,谢谢! - Jas
@Jas- 未定义行为并不意味着“不工作”。它可能会“似乎一直在工作”,直到在移动到新平台时出现无法解释的故障。到那时,您可能已经忘记了这篇文章,并不得不加班来找出您犯错的地方。 - StoryTeller - Unslander Monica
2
@Jas - 你不必使用typedef来遵循M.M的方法。关键是索引必须在转换之前发生。F = (int(*)(int, int))(functions[0]);。但再说一遍,一个包含函数指针的void*数组并不是C语言标准支持的东西。 - StoryTeller - Unslander Monica
@M.M 谢谢你指出这个问题!今天学到了新东西!我一直以为所有的指针大小都是相同的。 - akhilmd
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接