灵感来自对我的回答的评论。
这一系列步骤在C标准(C11)中是否合法?
或者相当于代码:
void foo(void) { ... } void bar(void) { ... } typedef void (*voidfunc)(void); voidfunc array[] = {foo, bar}; // Step 1 void *ptr1 = array; // Step 2 void *ptr2 = (char*)ptr1 + sizeof(voidfunc); // Step 3 voidfunc bar_ptr = *(voidfunc*)ptr2; // Step 4
我认为这是允许的,因为实际的函数指针只能通过正确的类型指针访问。 但Andrew Henle指出, 标准部分6.3.2.3似乎没有涵盖这一点:指针 。
是的,代码很好。 这里有各种陷阱和转换规则:
函数指针指向函数,但它们本身就是对象,就像任何指针一样。 因此,您可以使用void*
指向函数指针的地址 。
因此,使用void*
指向函数指针就可以了。 但不是用它直接指向一个函数。 如果是void *ptr1 = array;
数组衰变成指向第一个元素的指针, void (**)(void)
(在您的示例中等效于voidfunc*
)。 你可以指向一个带有void*
函数指针这样的指针。
此外,关于指针算术:
因此, (char*)ptr1 + sizeof(voidfunc);
也没关系。 然后,您将从void*
转换为voidfunc*
,转换为voidfunc*
,它是存储在数组中的原始函数指针类型。
正如在注释中所指出的,通过对函数类型使用typedef
,可以显着提高此代码的可读性:
typedef void (voidfunc)(void); voidfunc* array[] = {&foo, &bar}; // Step 1 void* ptr1 = array; // Step 2 void* ptr2 = (char*)ptr1 + sizeof(voidfunc*); // Step 3 voidfunc* bar_ptr = *(voidfunc**)ptr2; // Step 4
你的代码是正确的。
指向函数的指针是一个对象,并且您正在向对象 (指向函数指针的指针)转换指针以void
指针void
并再次返回; 然后最终取消引用指向对象的指针。
至于char
指针算术,这由C11的脚注106引用:
106)接近指针算术的另一种方法是首先将指针转换为字符指针:在此方案中,首先将转换后的指针中添加或减去的整数表达式乘以最初指向的对象的大小。 ,并将结果指针转换回原始类型。 对于指针减法,字符指针之间差异的结果类似地除以最初指向的对象的大小。 当以这种方式查看时,实现仅需要在对象结束之后提供一个额外字节(其可以与程序中的另一个对象重叠)以满足“超过最后一个元素”的要求。
void*
上的指针算法不在C语言中。 你不是这样做的,你在char*
上做指针运算,这是完全可以的。 您可以使用char*
而不是void*
开头。
Andrew Helne似乎错过了一个指向函数的指针是一个对象的事实,它的类型是一个对象类型。 这是一个简单明了的事实,不像其他一些评论家似乎暗示的那样掩盖在一片神秘的东西中。 因此,他反对投射指向函数指针的指针是没有根据的,因为指向任何对象类型的指针都可以转换为void*
。
但是,C标准似乎不允许使用(T*)((char*)p + sizeof(T))
代替(p+1)
(其中p
是指向类型数组元素的指针) T
),或者至少我在文中找不到这样的许可。 因此,您的代码可能不合法。
以上就是c/c++开发分享你可以将“指向函数指针的指针”转换为void *相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/559920.html