这一警告似乎没有必要. 在我的代码中,我有一个函数指针类型

(void*)(*function_pointer)(void* data)

有些函数需要这种类型的函数指针作为参数,因为它们不依赖于返回类型,它只需要是一个指针.

但是,当我传递像somestruct* function_A(void* data)这样的函数时 对于它,我得到了警告,即使somestruct*可以被隐式转换为void*,就像我可以将somestruct指针传递给函数int function_test(void* data)一样,它将在没有警告的情况下工作.

是的,我可以将function_A定义为void *作为返回类型,但这意味着所有出于其他原因使用该函数的人都必须将其返回值强制转换为somestruct *.我有两个 Select :让它保持原样,忽略让我有点恼火的警告,或者更改函数定义,这会让我更恼火.

因此,我在这里询问是否还有第三种 Select .

推荐答案

允许将任何对象指针转换为void *,但这不会传递到函数指针中的参数和返回类型.

指向函数somestruct* function_A(void*)的指针与类型void* (*function_pointer)(void*)的函数指针不兼容,因为返回类型不兼容.试图通过不兼容的指针类型调用函数将触发undefined behavior.

关于如何确定两种函数类型是否兼容的规则在C standard:

For two function types to be compatible, both shall specify compatible return types.此外,如果参数类型和参数类型都是 目前,应就参数的数量和使用达成一致 省略号终止符;对应的参数应兼容 类型.如果一种类型具有参数类型列表,而另一种类型为 由不是函数一部分的函数声明符指定 定义,并包含一个空标识符列表、参数 列表不应包含省略号终止符以及每个 参数应与从 应用默认参数提升.如果一种类型具有 参数类型列表,另一种类型由函数指定 包含(可能为空的)标识符列表的定义,两者 应就参数的数量和每个参数的类型达成一致 原型参数应与产生的类型兼容 从默认参数提升的应用程序到 相应的标识符.(在类型的确定中 兼容性和复合类型,每个参数都用 函数或数组类型被视为具有调整后的类型,并且每个 使用限定类型声明的参数被视为具有其声明类型的非限定版本.)

粗体部分是与本例相关的部分. void *和和 struct 体指针是不兼容的,即使允许在两者之间转换.

6.3.2.3p8节详细说明了函数指针转换的规则:

指向一种类型的函数的指针可以转换为指向 另一种类型的函数,然后再返回;结果将进行比较 等于原始指针.If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.

最后一节用粗体表示,你试图做的事情是不允许的.

您需要将函数的返回类型更改为void *,以与函数指针类型兼容.然而,强制转换返回类型并不是必需的,因为在没有返回类型的情况下允许在对象指针和void *之间进行转换.

C++相关问答推荐

Rust FFI--如何用给出返回引用的迭代器包装C风格的迭代器?

X86/x64上的SIGSEGV,由于原始内存访问和C中的DS寄存器之间的冲突,在Linux上用TCC编译为JIT引擎

为什么该函数不将参数值保存到数据 struct 中?

调用mProtection将堆栈上的内存设置为只读,直接导致程序SIGSEGV

如何在C语言中正确打印图形

C中的FREE函数正在触发断点

处理EPOLL_WAIT中的接收数据和连接关闭信号

如何在VS 2022中正确安装额外的C头文件

通过描述符查找文件路径时出现问题

CS50判断灯泡运动的问题,判断时多出一个灯泡,但不在终端上

GetText不适用于包含国际字符的帐户名称

C++中PUTS函数的返回值

如何在C宏定义中包含双引号?

共享目标代码似乎不能在Linux上的进程之间共享

C:面筋蛋白';为什么不刷新窗口?

C代码加密文件无法使用openssl解密

C++ 构建系统如何跟踪源文件中的更改?

关于将十六进制常量分配给signed类型变量的说明

在链接文件时无法解决多重定义错误

如何使用宏定义 struct 体 - 详细教程