我想投射一个指针pc
指向char到点pi
指向int
char *pc;
int *pi;
pi = (int*)pc // compiler complaint about old-style cast
pi = static_cast<int *>(static_cast<void *>(pc)) // no complaint any more but too complex
是否有任何更简单的方法来执行此演员并使编译器保持沉默?
我想在@Bathsheba's post下来回休息。所以这里是关于你正在做的更精细细节的答案。
@Sean already suggested你reinterpret_cast
你的指针。这相当于你的第二个演员阵容。它在[expr.reinterpret.cast]/7中说的很多:
可以将对象指针显式转换为不同类型的对象指针。当对象指针类型的prvalue
v
被转换为对象指针类型“指向cvT
的指针”时,结果是static_cast<cv T*>(static_cast<cv void*>(v))
。 [注意:将“指向T1
的指针”类型的prvalue转换为“指向T2
”的类型(其中T1
和T2
是对象类型,T2
的对齐要求不比T1
更严格)并返回其原始类型产生原始指针值。 - 结束说明]
现在,让我们来看看两步转换的每一步。首先,我们有一个static_cast<void*>
。根据[conv.ptr]/2(强调我的):
类型为“指向cv
T
的指针”的prvalue,其中T
是一个对象类型,可以转换为“指向cvvoid
的指针”类型的prvalue。此转换不会改变指针值。
第一次转换不会对地址进行任何更改。然后它也在[basic.compound]/5说:
指向cv-qualified或cv-nonqualified
void
的指针可用于指向未知类型的对象。这样的指针应该能够保存任何对象指针。 cvvoid*
类型的对象应具有与cvchar*
相同的表示和对齐要求。
因此,char*
可以存储void*
可能存储的任何地址。现在它并不意味着从void*
到char*
的转换是值保留,只是它们可以代表相同的值。现在,假设一个非常有限的用例,这足以保证。但在[expr.static.cast]/13还有更多:
类型为“指向cv1 void的指针”的prvalue可以转换为类型为“指向cv2 T的指针”的prvalue,其中T是对象类型,cv2是与cv1相同的cv-qualification,或更高的cv-qualification。如果原始指针值表示存储器中字节的地址A而A不满足T的对齐要求,则未指定结果指针值。否则,如果原始指针值指向对象a,并且存在类型为T(忽略cv-qualification)的对象b,该对象b是指针可互换的,则结果是指向b的指针。否则,转换指针值不变。
我要去哪里?假设pc
已经拥有int
的地址(根据上面适当转换),然后通过char*
将int*
投射到reinterpret_cast
将给你原始int
的地址。第一段下的说明同样多,而进一步的引用证明了这一点。如果它不能保持int
的地址,那么你正在玩轮盘赌并且很可能会失败。您的程序有未定义的行为。你应该按照芭丝谢芭的建议去写信。
如果你真的需要这样做,那么reinterpret_cast是你的朋友:
char *pc = 0;
int *pi = 0;
pi = reinterpret_cast<int*>(pc);
通常,转换为char*
指针的int*
指针的行为是未定义的。取消引用这样的指针将导致您进一步麻烦,因为您将破坏严格的别名规则。请注意,C ++标准不要求sizeof(char*)
与sizeof(int*)
相同。
(请注意,如果unsigned char*
指针实际指向int*
,则将unsigned char*
指针转换为int
是明确定义的)。
不要这样做。永远。