![](/img/trans.png)
[英]Where does the C++ standard describe the casting of pointers to primitives?
[英]Where does the C++ standard allow pointers to undefined types?
这在C ++规范中的何处允许? 这个很酷。 我想知道这是如何规范的。 我没有意识到规范允许使用指向未定义类型的指针。
class T;
int main(int argc, char* argv[])
{
int x;
T* p = reinterpret_cast<T*>(&x);
return 0;
}
在将指针强制转换为不相关的类型( char*
除外)之后,唯一要做的事情就是将其强制转换回原始指针类型。
@cli_hlt击败了我提供此部分。
这是规则本身:
可以将对象指针显式转换为其他类型的对象指针。 当prvalue
v
型“指针的T1
”被转换为类型“指针cv
T2
”,结果是static_cast<cv T2*>(static_cast<cv void*>(v))
如果两个T1
和T2
是标准-layout类型(3.9)和T2
的对齐要求并不比T1
严格,或者如果任一类型都是void
。 转换类型的prvalue“指针T1
”的类型“指针T2
”(其中T1
和T2
是对象类型,并且其中的对准要求T2
是不严格的比的T1
),并返回到其原始类型产生的原始指针值。 未指定任何其他此类指针转换的结果。
严格的别名规则禁止通过无关类型访问对象。 参见https://stackoverflow.com/a/7005988/103167
在第5.4节中找到了与您的问题有些相关的另一条规则:
使用强制转换表示法的强制转换操作数可以是“指向不完整类类型的指针”类型的prvalue。 使用
static_cast
符号的static_cast
目标类型可以是“指向不完整类类型的指针”如果操作数和目标类型都是类类型,并且一个或两个都不完整,则不确定是否使用static_cast
或reinterpret_cast
解释,甚至如果两个类之间存在继承关系。
您正在执行的操作可能是合法的,但这取决于class T
的实际定义,因此根据您显示的代码我们不确定。
从C ++ 11§3.9.2/ 3开始:
尽管可以使用不完整类型的指针进行限制,但仍可以使用它们。
这些限制在§3.2/ 4中列出:
如果满足以下条件,则类类型
T
必须是完整的:
- 定义了类型
T
的对象,或- 声明了类型
T
的非静态类数据成员,或者T
在new-expression中用作对象类型或数组元素类型,或者- 左值到右值的转换应用于引用类型
T
的对象的glvalue,或者- 表达式将(隐式或显式)转换为类型
T
,或者- 这不是一个空指针常量,并且具有比其他类型的表达式
void*
,被转换为类型指针T
或参考T
使用的隐式转换,一个dynamic_cast
或static_cast
,或- 类成员访问运算符应用于类型
T
的表达式,或者- 将
typeid
运算符或sizeof
运算符应用于类型T
的操作数,或者- 定义或调用了返回类型或参数类型为
T
的函数,或者- 定义了具有
T
类型的基类的类,或者- 将类型
T
的左值分配给,或- 类型
T
是alignof
表达式的主题,或者- 异常声明的类型为
T
,对T
引用或对T
指针。
第六届子弹出现此相关的,因为我们可以在§5.2.10/ 7看到, reinterpret_cast
指针类型之间的形式定义static_cast
:
可以将对象指针显式转换为其他类型的对象指针。 当将“指向
T1
指针”的prvaluev
转换为“指向T2
指针”时,如果T1
和T2
都是标准的,则结果为static_cast<cv T2*>(static_cast<cv void*>(v))
-layout类型和的对准要求T2
是不严格的比的T1
,或者如果任一类型是void
。 转换类型的prvalue“指针T1
”的类型“指针T2
”(其中T1
和T2
是对象类型,并且其中的对准要求T2
是不严格的比的T1
),并返回到其原始类型产生的原始指针值。 未指定任何其他此类指针转换的结果。
但是因为reinterpret_cast
static_cast
s首先设置为void*
, 然后再设置为实际的指针类型,所以第6个项目符号不适用。
因此,到目前为止,尽管T
是不完整的类型,但您仍处于合法范围内。 但是,如果事实证明T
不是标准布局类型或比int
更严格的对齐要求,则第5.2.10 / 7节中的最后一句话成立,您正在调用UB。
适用于您的情况的第5.2.10(7)节(根据ISO / IEC14882:1998(E),以及2011 FDIS中的规定)。
我不确定您认为允许什么。 可以保证您可以从一个指针类型reinterpret_cast
到足够大的其他指针类型,然后再次返回到原始类型,并将成为原始指针。 规范在5.2.10 [expr.reinterpret.cast]中。 即,保证以下工作:
T* ptr = ...;
S* sptr = reinterpret_cast<S*>(ptr);
T* tptr = reinterpret_cast<T*>(sptr);
assert(ptr == tptr);
我们在本周早些时候就该主题进行了闭门讨论:如果Death Station 9000实现(这是C ++的一致实现,但也尝试在允许这样做的地方打破用户代码),XOR会使用如果指针在程序执行开始时具有随机选择的位模式,则如果reinterpret_cast<T>(x)
中涉及的类型不涉及char
,则这将是允许的实现。 一致认为这是可以的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.