C ++规范中允许哪些内容?这很酷。我想知道这是怎么说的。我没有意识到规范允许指向未定义类型的指针。
class T;
int main(int argc, char* argv[])
{
int x;
T* p = reinterpret_cast<T*>(&x);
return 0;
}
答案 0 :(得分:4)
在将指针转换为不相关的类型(char*
除外)之后,您唯一允许的操作将被强制转换为原始指针类型。
@cli_hlt打败了我提供这个部分。
这是规则本身:
可以将对象指针显式转换为不同类型的对象指针。 当“指向
v
的指针”的prvalueT1
转换为“指向cv
T2
的指针”时,结果为{ {1}}如果static_cast<cv T2*>(static_cast<cv void*>(v))
和T1
都是标准布局类型(3.9),且T2
的对齐要求不比T2
更严格,或者类型为T1
。转换类型的prvalue “指向void
的指针”指向T1
的指针“(其中T2
和T1
是对象类型,T2
的对齐要求为否比T2
更严格,并返回其原始类型产生原始指针值。任何其他此类指针转换的结果都未指定。
严格别名规则禁止通过不相关的类型访问对象。见https://stackoverflow.com/a/7005988/103167
与您的问题有些相关的另一条规则见5.4节:
使用强制转换符号的强制转换操作数可以是“指向不完整类类型的指针”类型的prvalue。 使用强制转换表示法的强制类型转换的目标类型可以是“指向不完整类类型的指针”如果操作数和目标类型都是类类型且一个或两个都不完整,则未指定是否{{即使存在继承关系,也使用1}}或
T1
解释 两个班级之间。
答案 1 :(得分:4)
您正在做什么可能合法,但这取决于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
的指针。
第6个子弹在此处出现,正如我们在§5.2.10/ 7中所见,指针类型之间的 可以将对象指针显式转换为不同类型的对象指针。当“指向 但是因为 所以,到目前为止,尽管reinterpret_cast
是根据static_cast
定义的:< / p>
v
的指针”的prvalue T1
转换为“指向cv T2
的指针”时,如果static_cast<cv T2*>(static_cast<cv void*>(v))
T1
,结果为T2
T2
和T1
是标准布局类型,void
的对齐要求不比T1
更严格,或者两种类型都是T2
。将“指向T1
”的类型的prvalue转换为“指向T2
”的类型(其中T2
和T1
是对象类型,{{reinterpret_cast
的对齐要求1}}不比static_cast
更严格,并且返回其原始类型会产生原始指针值。任何其他此类指针转换的结果都未指定。void*
T
首先到T
,然后到实际结果指针类型,所以第6个子弹不适用。int
是一个不完整的类型,你仍处于合法领域。但是,如果事实证明{{1}}不是标准布局类型或者比{{1}}具有更严格的对齐要求,则§5.2.10/ 7中的最后一句成立并且您正在调用UB
答案 2 :(得分:2)
第5.2.10(7)节针对您的案例(自ISO / IEC14882:1998(E)以及2011年FDIS)。
答案 3 :(得分:0)
我不确定你认为被允许的是什么。保证您可以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 ++的实现,但也试图打破用户代码,只要它允许这样做)XORs位如果reinterpret_cast<T>(x)
中涉及的类型不涉及char
,那么在程序执行开始时随机选择的位模式的指针模式将是允许的实现。大家一致认为这是可以的。