我想将一个指向pi
的指针指向一个点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
,指向int
{{1}}
有没有更简单的方法来执行此转换并使编译器静音?
答案 0 :(得分:7)
如果你真的需要这样做,那么reinterpret_cast就是你的朋友:
char *pc = 0;
int *pi = 0;
pi = reinterpret_cast<int*>(pc);
答案 1 :(得分:6)
一般来说,转换char*
指向int*
指针的行为是 undefined 。取消引用这样的指针会导致您进一步麻烦,因为您将破坏严格别名规则。请注意,C ++标准不要求sizeof(char*)
与sizeof(int*)
相同。
(请注意,如果unsigned char*
指针实际指向int*
,则将unsigned char*
指针转换为int
是明确定义的。
答案 2 :(得分:1)
我想在@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
”的类型为“指向T2
”的类型的prvalue(其中T1
和T2
是对象类型,T2
的对齐要求是 没有比T1
更严格的并且回到它的原始类型产生 原始指针值。 - 结束说明]
现在,让我们来看看两步转换的每一步。首先我们有一个static_cast<void*>
。根据{{3}}(强调我的):
类型为“指向cv
T
的指针”的prvalue,其中T
是对象类型,可以是 转换为“指向cvvoid
的指针”的prvalue。 指针值 此转换未更改。
第一次转换不会对地址进行任何更改。然后它也在[conv.ptr]/2中说:
指向cv-qualified或cv-unqualified
void
的指针可用于指向 对于未知类型的对象。这样的指针应该可以容纳任何指针 对象指针。 cvvoid*
类型的对象应具有相同的对象 表示和对齐要求为cvchar*
。
因此char*
可以存储void*
可能存储的任何地址。现在,这并不意味着从void*
到char*
的转换是值保留,只是它们可以表示相同的值。现在,假设一个非常有限的用例,这足以保证。但是[basic.compound]/5还有更多内容:
“指向cv1 void的指针”类型的prvalue可以转换为prvalue 类型为“指向cv2 T的指针”,其中T是对象类型,cv2是 与cv1相同的cv资格,或更高的cv资格。如果 原始指针值表示一个字节的地址A. 内存和A不满足T的对齐要求,那么 结果指针值未指定。否则,如果是原件 指针值指向一个对象a,并且有一个类型的对象b T(忽略cv资格),指针可与a互换, 结果是指向b的指针。 否则,指针值为 转换未改变。
我要去哪里?假设pc
已经拥有int
的地址(根据上述内容进行了适当转换),那么char*
通过int*
投放到reinterpret_cast
会给你原始int
的地址。第一段下的说明同样多,而进一步的引用证明了这一点。如果它不包含int
的地址,则表示您正在玩轮盘赌而且可能会丢失。您的程序有未定义的行为。你应该遵循芭丝谢芭对这封信的建议。