将长整型转换为函数指针?

5

I have the following code:

long fp = ...
void (*ptr)(long, char*, char*) = fp;

长的 fp 是一个正确的函数指针,它作为一个长整型传递。我得到了标准的“从整数转换而来的指针没有显式类型转换”的警告。我想能够编译通过:

-std=iso9899:1990 -pedantic-errors

这会将警告转化为错误。问题是:什么是正确的类型转换?我尝试了各种猜测,例如:

void (*ptr)(long, char*, char*) = (void)(*)(long, char*, char*) fp;

但是似乎找不到合适的。

为什么你想要这样做? - Oliver Charlesworth
整数和函数指针之间的转换? - Oliver Charlesworth
如果fp一开始就是正确的函数指针,为什么它会被存储在一个长整型中呢?也许你应该集中精力确保输入正确,而不是试图事后想出一个权宜之计。 - Mr Lister
3
我会尽力完成翻译。以下是内容的翻译:我更希望得到有关演员阵容的答案,而不是重新设计。JNI引入了许多问题,其中这个问题是最小的。 - gub
2
@MrLister:有时候这并不取决于你。在Windows编程中,将任何类型的指针传递到wndproc的参数中是常见做法,这些参数保证足够大以容纳此类内容。可能OP正在使用一个执行此类操作的库。 - Matteo Italia
此外,dlsym调用(POSIX)和GetProcAddress(Windows)需要将整数转换为函数指针。 - scravy
4个回答

8
"正确"的转换方式是:
void (*ptr)(long, char*, char*) = (void (*)(long, char*, char*))fp;

显然,使用适当的typedef可以整理这个问题。

但无论如何,其结果是由实现定义的。如果可能的话,避免这种情况,并将指针保持为指针类型。下一个最好的选择是如果可用,使用intptr_t


7

可能是类似以下内容:

void (* ptr)(long, char, char *) = (void (*)(long, char, char *))fp;

但是我的建议是使用 typedef 并忘记所有这些混乱:

typedef void (* fnPtr)(long, char, char*);
fnPtr ptr = (fnPtr) fp;

4
唯一“正确”的方法是根本不需要转换,而是复制二进制表示:
long fp;
void (*ptr)(long, char*, char*);

memcpy(&ptr, &fp, sizeof ptr);

除非sizeof(long) != sizeof(ptr),否则它不会灾难性地失败。 - jørgensen

2
主要问题在于,尽管有无数依赖于此功能的C-API,但ANSI-C不允许这样做。因此,在使用-pedantic编译时可能会遇到麻烦。 正如其他帖子中所暗示的那样,您可以通过使用memcpy()或联合类型进行强制转换来欺骗字面值转换。
顺便说一下,POSIX保证这将起作用,因此关于“实现定义的结果”的部分会变得不那么可怕。

C99明确允许这样做,只是指出结果是实现定义的。 - Oliver Charlesworth
很酷,我不知道那个。我主要是C++程序员,所以我更熟悉C89,据我所知它不允许这样做。 - ComicSansMS

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