为什么不能将函数指针转换为(void *)? [英] Why can't I cast a function pointer to (void *)?

查看:199
本文介绍了为什么不能将函数指针转换为(void *)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,它接收一个字符串,一个字符串数组和一个指针数组,并在字符串数组中查找该字符串,然后从指针数组中返回相应的指针.由于我将它用于几种不同的事情,因此将指针数组声明为(void *)的数组,并且调用方应知道实际上存在哪种指针(因此,它将返回哪种指针作为返回值) ).

I have a function that takes a string, an array of strings, and an array of pointers, and looks for the string in the array of strings, and returns the corresponding pointer from the array of pointers. Since I use this for several different things, the pointer array is declared as an array of (void *), and the caller should know what kind of pointers are actually there (and hence what kind of a pointer it gets back as the return value).

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

When I pass in an array of function pointers, however, I get a warning when I compile with -Wpedantic:

c声:

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

gcc:

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":

Here's a test file, which despite the warning does correctly print "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函数外,是否有任何方法可以解决该警告,一次用于函数指针,一次用于非函数指针?有没有更好的方法可以实现我想要做的事情?

Is there any way to fix the warning, other than not compiling with -Wpedantic, or duplicating my find_ptr function, once for function pointers and once for non-function pointers? Is there a better way to achieve what I'm trying to do?

推荐答案

您无法解决该警告.实际上,在我看来,这应该是一个很难的错误,因为将函数指针转换为其他指针是非法的,因为当今存在的体系结构不仅违反了C标准,而且是使代码成为现实的错误.不行.编译器允许这样做,因为即使这些程序在某些其他体系结构上会严重崩溃,但许多体系结构还是放弃了它.但这不仅是理论上的违反标准,还会导致真正的错误.

You can't fix the warning. In fact, in my opinion it should be a hard error since it's illegal to cast function pointers to other pointers because there are architectures out there today where this isn't just a violation of the C standard but an actual error that will make the code not work. Compilers allow it because many architectures get away with it even though those programs will crash badly on some other architectures. But it's not just a theoretical standard violation, it's something that causes real bugs.

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

For example on ia64 function pointers are (or at least used to be last time I looked) actually two values, both necessary to make function calls across shared libraries or a program and a shared library. Likewise, the common practice to cast and call function pointers to functions returning a value to a pointer to a function returning void because you know you'll ignore the return value anyway is also illegal on ia64 because that can lead to trap values leaking into registers causing crashes in some unrelated piece of code many instructions later.

不强制转换函数指针.始终使它们具有匹配类型.这不仅是标准的方法,而且是重要的最佳实践.

Don't cast function pointers. Always have them match types. This is not just standards pedantry, it's an important best practice.

这篇关于为什么不能将函数指针转换为(void *)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆