我已经多次看到并使用过这个是 C++,特别是在各种线程实现中。我想知道这样做是否有任何陷阱/问题?当我们强制转换为 void* 并再次返回时,有什么方法可以让我们遇到错误或未定义的情况?如果有这些问题,我们应该如何解决?
谢谢你。
我已经多次看到并使用过这个是 C++,特别是在各种线程实现中。我想知道这样做是否有任何陷阱/问题?当我们强制转换为 void* 并再次返回时,有什么方法可以让我们遇到错误或未定义的情况?如果有这些问题,我们应该如何解决?
谢谢你。
这是完全有效的。以下是标准对它的评价:
§4.10 指针转换
2 “指向cv
T
的指针”类型的右值,其中T
是对象类型,可以转换为“指向cvvoid
的指针”类型的右值。将“指向cv的指针”转换为“指向cv 的指针”的结果指向类型对象所在的存储位置的开始,就好像该对象是最派生的类型对象 (1.8) (即不是基类子对象)。T
void
T
T
这意味着您可以将指向类的指针转换为 void 指针。和 ...
§5.2.9 静态演员表
10 “指向cv
void
的指针”类型的右值可以显式转换为指向对象类型的指针。指向对象的指针类型的值转换为“指向cvvoid
的指针”并返回到原始指针类型将具有其原始值。
这意味着您可以使用static_cast
将 void 指针转换回原始类指针。
希望能帮助到你。祝你好运!
在 C++ 中,您不需要静态强制转换即可 void*
:
int main()
{
CFoo* foo = new CFoo;
void* dt = foo;
tfunc(dt); // or tfunc(foo);
return 0;
}
注意:您的实现tfunc()
是非常正确的,因为它确实需要演员表。
我在 C++ 中没有看到太多的转换。void*
这是 C 中的一种实践,在 C++ 中被积极避免。
转换为void*
删除所有类型的安全性。
如果您使用reinterpret_cast
orstatic_cast
将指针类型转换为相同的void*
指针类型并返回到相同的指针类型,则标准实际上保证了结果将是明确定义的。
危险在于您可能将 avoid*
转换为错误的类型,因为您不再确定正确的类型是什么。
我想知道这样做是否有任何陷阱/问题?
在将 back 转换为特定类型时,您需要绝对确定void*
,如果不这样做,您最终会遇到未定义的行为和潜在的灾难。一旦你使用void *
你就会失去类型安全性。很难跟踪 avoid *
实际指向的类型,没有办法保证或确定它确实指向你要将它类型转换回的类型。
当我们强制转换为 void* 并再次返回时,有什么方法可以让我们遇到错误或未定义的情况?
是的,中提到的场景#1
。
如果有这些问题,我们应该如何解决?
完全避免void *
在 C++ 中使用,而是使用模板和继承。
在 C 语言中,您可能在某些情况下绝对需要它,但尽量将其使用降至最低。
归根结底,
C/C++ 允许您用脚射击自己,这取决于您是否这样做。
标准授予的唯一一件事是,给定A* pa
, (A*)(void*)pA == pA
。一个后果
void* pv = pA;
A* pA2 = (A*)pv;
pA2->anything ...
将与pA->anything ...
其他一切都是“未定义的”,广告 - 事实上 - 在某种程度上依赖于实现。
根据我的经验,这里有一些已知的陷阱:
A
派生形式B
,pA
并且pB
是A*
和B*
。 pB=pA
使pB
指向 的基数A
。那并不意味着pB
并且pA
是相同的地址。因此pB = (B*)(void*)pA
实际上可以将其他任何地方指向 A (尽管通常实现单继承对象共享相同的起源,所以它显然工作正常)pB
实际上指向 a A
,pA = (A*)(void*)pB
不一定正确指向 A 对象。正确的方法是pA = static_cast<A*>(pB);
class A: public Z, public B { ... };
如果Z
不为空,给定 an A
,B
子组件将不会具有相同的 A 地址。(并且 C++ 中的多重继承无处不在 iostream 是)(char*)(void*)pI
指向pI
整数的地方)与“ *pI
if *pI
in(-128..+127)”不同(仅在小端机器上)一般来说,不要假设类型之间的转换只是改变解释地址的方式。
我知道驱动程序等中的很多函数使用 void 指针将数据返回给调用者,架构大致相同:
int requestSomeData(int kindOfData, void * buffer, int bufferSize);
该函数可以将不同的数据类型作为参数。他们所做的是使用 bufferSize 作为参数来避免写入他们不应该写入的内存位置。如果 bufferSize 不匹配或小于应返回的数据,则该函数将返回错误代码。
无论如何:避免使用它们或在编写任何代码之前三思而后行。
这是有效的吗?
是的,根据标准 § 5.2.9.7 它是有效的
“指向 cv1 void 的指针”类型的纯右值可以转换为“指向 cv2 T 的指针”类型的纯右值,其中 T 是对象类型,而 cv2 与 cv1 具有相同的 cv 限定或大于 cv1 的 cv 限定。空指针值转换为目标类型的空指针值。指向对象的指针类型的值转换为“指向 cv void 的指针”并返回,可能具有不同的 cv 限定,应具有其原始值。[ 例子:
T* p1 = new T;
const T* p2 = static_cast<const T*>(static_cast<void*>(p1));
bool b = p1 == p2; // b will have the value true.