gpt4 book ai didi

c - 为什么我不能将函数指针强制转换为 (void *)?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:50:24 27 4
gpt4 key购买 nike

我有一个函数,它接受一个字符串、一个字符串数组和一个指针数组,并在字符串数组中查找字符串,并从指针数组中返回相应的指针。因为我将它用于几个不同的事情,所以指针数组被声明为 (void *) 的数组,并且调用者应该知道实际存在什么样的指针(因此它返回什么样的指针作为返回值).

但是,当我传入一个函数指针数组时,我在使用 -Wpedantic 进行编译时收到警告:

clang :

test.c:40:8: warning: assigning to 'voidfunc' (aka 'void (*)(void)') from 'void *' converts
between void pointer and function pointer [-Wpedantic]

海湾合作委员会:

test.c:40:8: warning: ISO C forbids assignment between function pointer and ‘void *’ [-Wpedantic]
fptr = find_ptr("quux", name_list, (void **)ptr_list,

这是一个测试文件,尽管有警告,但它确实正确地打印了“quux”:

#include <stdio.h>
#include <string.h>

void foo(void)
{
puts("foo");
}

void bar(void)
{
puts("bar");
}

void quux(void)
{
puts("quux");
}

typedef void (* voidfunc)(void);

voidfunc ptr_list[] = {foo, bar, quux};

char *name_list[] = {"foo", "bar", "quux"};

void *find_ptr(char *name, char *names[], void *ptrs[], int length)
{
int i;

for (i = 0; i < length; i++) {
if (strcmp(name, names[i]) == 0) {
return ptrs[i];
}
}
return NULL;
}

int main() {
voidfunc fptr;

fptr = find_ptr("quux", name_list, (void **)ptr_list,
sizeof(ptr_list) / sizeof(ptr_list[0]));
fptr();

return 0;
}

除了不使用 -Wpedantic 进行编译,或者复制我的 find_ptr 函数(一次用于函数指针,一次用于非函数指针)之外,还有什么方法可以修复警告吗?有没有更好的方法来实现我想要做的事情?

最佳答案

您无法修复警告。事实上,在我看来,这应该是一个硬错误,因为将函数指针转换为其他指针是非法的,因为当今的体系结构中,这不仅违反了 C 标准,而且是一个实际错误,将使代码不行。编译器允许它,因为即使这些程序在其他一些体系结构上会严重崩溃,许多体系结构也会逃脱它。但这不仅仅是理论上的标准违规,它会导致真正的错误。

例如,在 ia64 上,函数指针实际上是(或者至少曾经是我上次查看的)两个值,这两个值都是跨共享库或程序和共享库进行函数调用所必需的。同样,将函数指针强制转换和调用到返回值的函数的函数指针的常见做法是返回指向返回 void 的函数的指针,因为您知道无论如何都会忽略返回值,这在 ia64 上也是非法的,因为这可能导致陷阱值泄漏到寄存器中在许多指令之后导致一些不相关的代码段崩溃。

不要转换函数指针。始终让它们匹配类型。这不仅仅是标准的迂腐,而是一种重要的最佳实践。

关于c - 为什么我不能将函数指针强制转换为 (void *)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39175936/

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