gpt4 book ai didi

c - 转换为不同签名的函数指针

转载 作者:太空狗 更新时间:2023-10-29 16:32:32 26 4
gpt4 key购买 nike

我使用一个函数指针结构来为不同的后端实现一个接口(interface)。签名差别很大,但返回值几乎都是void、void *或int。


struct my_interface {
void (*func_a)(int i);
void *(*func_b)(const char *bla);
...
int (*func_z)(char foo);
};

但并不要求后端支持每个接口(interface)函数的函数。所以我有两种可能性,第一种选择是在每次调用之前检查指针是否不等于 NULL。我不太喜欢这样,因为可读性差,而且我担心性能会受到影响(不过我还没有对其进行测量)。另一种选择是使用虚拟函数,在极少数情况下接口(interface)函数不存在。

因此我需要为每个签名设置一个虚拟函数,我想知道是否可以只为不同的返回值设置一个虚拟函数。并将其转换为给定的签名。


#include <stdio.h>

int nothing(void) {return 0;}

typedef int (*cb_t)(int);

int main(void)
{
cb_t func;
int i;

func = (cb_t) nothing;
i = func(1);

printf("%d\n", i);

return 0;
}

我用 gcc 测试了这段代码,它可以工作。但它是理智的吗?或者它会破坏堆栈还是会导致其他问题?

编辑:多亏了所有的答案,在进一步阅读之后,我现在学到了很多关于调用约定的知识。现在对引擎盖下发生的事情有了更好的理解。

最佳答案

根据 C 规范,转换函数指针会导致未定义的行为。事实上,有一段时间,GCC 4.3 预发布版会在您转换函数指针时返回 NULL,这在规范中是完全有效的,但他们在发布前取消了该更改,因为它破坏了很多程序。

假设 GCC 继续做它现在所做的事情,它将在默认的 x86 调用约定(以及大多数架构上的大多数调用约定)下正常工作,但我不会依赖它。在每个调用点针对 NULL 测试函数指针并不比函数调用昂贵多少。如果你真的想要,你可以写一个宏:

#define CALL_MAYBE(func, args...) do {if (func) (func)(## args);} while (0)

Or you could have a different dummy function for every signature, but I can understand that you'd like to avoid that.

Edit

Charles Bailey called me out on this, so I went and looked up the details (instead of relying on my holey memory). The C specification says

766 A pointer to a function of one type may be converted to a pointer to a function of another type and back again;
767 the result shall compare equal to the original pointer.
768 If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.

and GCC 4.2 prereleases (this was settled way before 4.3) was following these rules: the cast of a function pointer did not result in NULL, as I wrote, but attempting to call a function through a incompatible type, i.e.

func = (cb_t)nothing;
func(1);

在您的示例中,将导致中止。他们改回 4.1 行为(允许但警告),部分原因是此更改破坏了 OpenSSL,但 OpenSSL 已在此期间得到修复,这是编译器可以随时更改的未定义行为。

OpenSSL 只是将函数指针转换为其他函数类型,这些函数类型采用并返回相同数量的相同大小的值,并且这(假设您不处理 float )恰好在所有平台上都是安全的,并且我知道的调用约定。但是,其他任何东西都可能不安全。

关于c - 转换为不同签名的函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/188839/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com