Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何检查void*指针是否可以安全地转换到其他对象?_C_Pointers_Casting_Void_Void Pointers - Fatal编程技术网

C 如何检查void*指针是否可以安全地转换到其他对象?

C 如何检查void*指针是否可以安全地转换到其他对象?,c,pointers,casting,void,void-pointers,C,Pointers,Casting,Void,Void Pointers,假设我有这个函数,它是一些gui工具包的一部分: typedef struct _My_Struct My_Struct; /* struct ... */ void paint_handler( void* data ) { if ( IS_MY_STRUCT(data) ) /* <-- can I do something like this? */ { My_Struct* str = (My_Struct*) data; } } /* in ma

假设我有这个函数,它是一些gui工具包的一部分:

typedef struct _My_Struct My_Struct;
/* struct ... */

void paint_handler( void* data )
{
   if ( IS_MY_STRUCT(data) ) /* <-- can I do something like this? */
   {
      My_Struct* str = (My_Struct*) data;
   }
}

/* in main() */
My_Struct s;
signal_connect( SIGNAL_PAINT, &paint_handler, (void*) &s ); /* sent s as a void* */
typedef struct\u我的结构我的结构;
/*结构*/
无效绘制处理程序(无效*数据)
{

如果(是我的结构(数据))/*您的
void
指针会丢失其所有类型信息,因此仅此一点,您无法检查它是否可以安全地强制转换。由程序员决定
void*
是否可以安全地强制转换为类型。

不幸的是,在指针出现在该上下文(void)之前,没有功能检查它是什么


我能想到的一个解决方案是,将int _struct_id作为所有结构的第一个成员。然后,无论类型如何,都可以安全地检查此id成员,但如果传递的指针未实现此成员(或int、char、…指针),则此操作将失败c中真的没有指针。
void
指针是无类型的,只有当您真正知道它们指向什么时才应该进行铸造


也许你应该重新考虑你的设计;重写你的代码,这样就不需要检查了。这也是谷歌不允许RTTI的原因。

你能做的最好的事情就是查看哪些数据点,看看它是否有你想要的信号,尽管a)它不会接近保证,b)可能是危险的,因为你不知道数据实际指向的东西有多大。我想这并不比使用它更危险,但是(正如有人建议的)重新设计会更好。

如果您正在创建正在使用的类型,您可以在类型中包含某种标识信息,以帮助您排除某些无效指针不是您正在寻找的类型。同时,您可能会遇到一些随机内存区域包含相同数据或作为你正在寻找的东西,至少你会知道什么时候不是你正在寻找的类型

这种方法需要以这样的方式初始化结构:用于确定内存区域是否无效的签名成员被初始化为签名值

例如:

typedef struct {
    ULONG  ulSignature1;
    //  .. data elements that you want to have
    ULONG  ulSignature2;
} MySignedStruct;
#define MYSIGNEDSTRUCT_01  0x1F2E3D4C
#define MYSIGNEDSTRUCT_02  0xF1E2D3C4

#define IS_MY_STRUCT(sAdr)  ( (((MySignedStruct *)sAdr)->ulSignature1 == MYSIGNEDSTRUCT_01  ) && (((MySignedStruct *)sAdr)->ulSignature1 == MYSIGNEDSTRUCT_02))

这是一种粗略的方法,但它可以提供帮助。自然地,如果参数有副作用,那么使用像
is_MY_STRUCT()
其中
xStruct
是指向
MySignedStruct

的指针,我知道这个问题已经问了3年了,但现在我来了,
使用一个简单的全局枚举来区分调用函数的位置如何。然后您可以在将void指针强制转换到的类型之间进行切换。

可能不是您所需要的,但我认为可以通过GObject进行一些类型检查system@another.anon.coward是的,我曾经在我的代码中使用它,但它需要10亿个宏这就是为什么,如果我拿起我3个月前写的一段GObject代码,我将无法理解它的头尾(这是一个很酷的解决方案,但请注意:如果释放指针,_struct_id可能仍然具有正确的值。然后,可能会出现其他对象在其四个字节中具有完全相同的值的情况。例如,如果您的_struct_id为0,您可以打赌这不会起作用,因为有太多其他对象在其前四个字节中具有0。如果y如果你采用这种方法,就可以编一些疯狂的东西,比如0x582fb603。不过,要知道,总有可能其他东西也会有相同的字节。有了这种可靠性,也许可以在断言或调试构建中使用它,但不能用其他方式。你的答案看起来没有错,但你可以改进它。只要看一看。