gpt4 book ai didi

空指针和指向函数指针的指针之间的转换

转载 作者:太空宇宙 更新时间:2023-11-03 23:24:22 24 4
gpt4 key购买 nike

我知道 void * 并且函数指针无法安全地转换。

我的问题是下面的代码。

#include <stdio.h>
#include <stdlib.h>

void f(void *);

void g(void) {
printf("hello world\n");
}

int main(void) {
void (*p)(void) = g;
void (**pp)(void) = malloc(sizeof(void (*)(void)));
pp = &p;
f(pp);
free(pp); //segfault
return EXIT_SUCCESS;
}

void f(void *p) {
(*(void (**)(void))p)();
}

它在 gcc 中使用 -Wall -Wextra -pedantic -std=c99 编译良好,但在程序调用 free 时在运行时失败。在这种情况下有什么问题?指向函数指针的指针不是数据指针吗?

事后思考:

正确的代码是这样的,

int main(void) {
void (*p)(void) = g;
f(&p);
return EXIT_SUCCESS;
}

我不知道为什么我会感到困惑:/

最佳答案

您的代码中存在错误:

您首先为函数指针分配空间并将地址存储在pp 中。

void (**pp)(void) = malloc(sizeof(void (*)(void)));

然后你立即用局部函数函数p的地址覆盖它:

pp = &p;

您调用 f(),后者会调用传递地址处的函数指针。

f(pp);

最后,您尝试释放 局部变量的地址,这是未定义的行为,您的环境会崩溃。

free(pp); //segfault

您可能打算将 p 的值存储在分配的对象中,而不是 pp = &p;:

*pp = p;

您关于转换 void * 和函数指针的评论是正确的:void * 指针不能安全地转换为 void(*)()反之亦然。对象指针和函数指针可能具有不同的不兼容表示。

在您的情况下,您将 void * 的返回值从 malloc() 隐式转换为指向函数指针 void (**)() 的指针。这种转换是正确的,因为 malloc 被定义为返回一个适合存储任何对象类型的指针(前提是分配了足够的空间)。

相应地,当将指针 pp 传递给 f 时,您将其隐式转换为 void *,后者又将其转换回 >无效 (**)()。定义这样的转换是因为任何对象指针都可以安全地转换为 void * 并返回其原始类型。为了完整起见,所有函数指针都可以安全地从一种类型转换为另一种类型,只要它们在调用之前转换为引用函数的实际类型即可。

关于空指针和指向函数指针的指针之间的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30721187/

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