学习并弄乱了函数指针,我注意到了一种初始化void函数指针并转换它们的方法。 然而,虽然我没有收到任何警告或错误,无论是使用GCC还是VS的编译器,我都想知道这样做是危险的还是坏的做法,因为我没有看到这种方法经常初始化函数指针互联网。 而且,我们称之为通用函数指针吗?
#include #include #include #define PAUSE (_getch()) uint16_t add(const uint16_t x, const uint16_t y) { return x + y; } char chr(uint8_t test) { return (char)test; } int main(void) { void(*test)() = (void*)add; const uint16_t x = 1, y = 1; uint16_t value = ((uint16_t(*)())test)(x, y); test = (void*)chr; printf("%dn", add(x, y)); // 2 printf("%dn", value); // 2 printf("%cn", ((char(*)())test)(100)); // d PAUSE; return 0; }
这是一个通用的函数指针
不,如果我不是非常错误,那么C中没有“generics函数指针”这样的东西。
这是危险的吗?
是的。 这是邪恶的。
您需要了解一些事项。 首先,除非您运行的系统符合POSIX,
void(*test)() = (void*)add;
是错的。 void *
是一个指向对象的指针类型,因此它与函数指针不兼容。 (至少在标准C中没有 – 正如我所提到的,POSIX也要求它与函数指针兼容。)
第二件事是void (*fp)()
和void (*fp)(void)
是不同的。 前一个声明允许fp
获取任意类型的任意数量的参数,并且当编译器看到对函数(指针)的第一次调用时,将推断出参数的数量及其类型。
另一个重要的方面是保证函数指针可以相互转换(AFAIK这表明它们具有相同的表示和对齐要求)。 这意味着任何函数指针都可以分配给任何函数的(地址)(在适当的强制转换之后),只要你不通过指向不兼容类型的指针调用函数。 当且仅当您在调用指针之前将指针强制转换回原始类型时,行为才是明确定义的。
所以,如果你想要一个“通用”函数指针,你可以写一些像
typedef void (*fn_ptr)(void);
然后你可以将任何指向函数的指针fn_ptr
类型的对象。 您需要注意的是,在调用函数时,再次转换为正确的类型,如:
int add(int a, int b); fn_ptr fp = (fn_ptr)add; // legal fp(); // WRONG! int x = ((int (*)(int, int))fp)(1, 2); // good
这里有两个严重的问题:
还有两个较小的问题:
您可能会使用此方法来破坏调用堆栈,具体取决于调用约定,特别是谁正在进行清理: http : //en.wikipedia.org/wiki/X86_calling_conventions对于被调用者清理,编译器无法知道您有多少变量已经在清理点上传递了堆栈,因此传递错误数量的参数或错误大小的参数将最终破坏调用堆栈。
在x64上,每个人都使用调用者清理,因此在这方面你是安全的。 然而,参数值通常是一团糟。 在您的示例中,在x64上,它们将是当时相应寄存器中的任何内容。
C11§6.3.2.3(8)说:
指向一种类型的函数的指针可以被转换为指向另一种类型的函数的指针并且再次返回; 结果应该等于原始指针。 如果转换的指针用于调用类型与引用类型不兼容的函数,则行为未定义。
§6.7.6.3(15)说关于兼容的function类型:
[…]如果一个类型具有参数类型列表而另一个类型由函数声明符指定,该函数声明符不是函数定义的一部分且包含空标识符列表,则参数列表不应具有省略号终止符和类型每个参数应与应用默认参数促销产生的类型兼容。 […]
所以,如果你有add
和chr
来获取int
参数(一个int的宽度至少为16位),那就没问题(如果你没有将函数指针强制转换为void *
),但实际上,它是是UB。
需要了解更多c/c++开发分享这是一个通用的函数指针,它是危险的吗?,也可以关注C/ C++技术分享栏目—计算机技术网(www.ctvol.com)!
以上就是c/c++开发分享这是一个通用的函数指针,它是危险的吗?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/979588.html