[英]Where does the C++ standard allow pointers to undefined types?
Where in the C++ spec is this allowed? 这在C ++规范中的何处允许? It's cool.
这个很酷。 I want to know how this is spec'd.
我想知道这是如何规范的。 I didn't realize the spec allowed having a pointer to a undefined type.
我没有意识到规范允许使用指向未定义类型的指针。
class T;
int main(int argc, char* argv[])
{
int x;
T* p = reinterpret_cast<T*>(&x);
return 0;
}
The only thing you're allowed to do after casting a pointer to an unrelated type (other than char*
), is cast back to the original pointer type. 在将指针强制转换为不相关的类型(
char*
除外)之后,唯一要做的事情就是将其强制转换回原始指针类型。
@cli_hlt beat me to providing the section. @cli_hlt击败了我提供此部分。
Here's the rule itself: 这是规则本身:
An object pointer can be explicitly converted to an object pointer of a different type.
可以将对象指针显式转换为其他类型的对象指针。 When a prvalue
v
of type "pointer toT1
" is converted to the type "pointer tocv
T2
", the result isstatic_cast<cv T2*>(static_cast<cv void*>(v))
if bothT1
andT2
are standard-layout types (3.9) and the alignment requirements ofT2
are no stricter than those ofT1
, or if either type isvoid
.当prvalue
v
型“指针的T1
”被转换为类型“指针cv
T2
”,结果是static_cast<cv T2*>(static_cast<cv void*>(v))
如果两个T1
和T2
是标准-layout类型(3.9)和T2
的对齐要求并不比T1
严格,或者如果任一类型都是void
。 Converting a prvalue of type "pointer toT1
" to the type "pointer toT2
" (whereT1
andT2
are object types and where the alignment requirements ofT2
are no stricter than those ofT1
) and back to its original type yields the original pointer value.转换类型的prvalue“指针
T1
”的类型“指针T2
”(其中T1
和T2
是对象类型,并且其中的对准要求T2
是不严格的比的T1
),并返回到其原始类型产生的原始指针值。 The result of any other such pointer conversion is unspecified.未指定任何其他此类指针转换的结果。
The strict aliasing rule prohibits access to an object through an unrelated type. 严格的别名规则禁止通过无关类型访问对象。 See https://stackoverflow.com/a/7005988/103167
参见https://stackoverflow.com/a/7005988/103167
Another rule somewhat related to your question is found in section 5.4: 在第5.4节中找到了与您的问题有些相关的另一条规则:
The operand of a cast using the cast notation can be a prvalue of type "pointer to incomplete class type".
使用强制转换表示法的强制转换操作数可以是“指向不完整类类型的指针”类型的prvalue。 The destination type of a cast using the cast notation can be "pointer to incomplete class type" If both the operand and destination types are class types and one or both are incomplete, it is unspecified whether the
static_cast
or thereinterpret_cast
interpretation is used, even if there is an inheritance relationship between the two classes.使用
static_cast
符号的static_cast
目标类型可以是“指向不完整类类型的指针”如果操作数和目标类型都是类类型,并且一个或两个都不完整,则不确定是否使用static_cast
或reinterpret_cast
解释,甚至如果两个类之间存在继承关系。
What you're doing may be legal, but that depends on the real definition of class T
, so we can't know for sure based on the code you've shown. 您正在执行的操作可能是合法的,但这取决于
class T
的实际定义,因此根据您显示的代码我们不确定。
Starting with C++11 §3.9.2/3: 从C ++ 11§3.9.2/ 3开始:
Pointers to incomplete types are allowed although there are restrictions on what can be done with them.
尽管可以使用不完整类型的指针进行限制,但仍可以使用它们。
Those restrictions are listed in §3.2/4: 这些限制在§3.2/ 4中列出:
A class type
T
must be complete if:如果满足以下条件,则类类型
T
必须是完整的:
- an object of type
T
is defined, or定义了类型
T
的对象,或- a non-static class data member of type
T
is declared, or声明了类型
T
的非静态类数据成员,或者T
is used as the object type or array element type in a new-expression , orT
在new-expression中用作对象类型或数组元素类型,或者- an lvalue-to-rvalue conversion is applied to a glvalue referring to an object of type
T
, or左值到右值的转换应用于引用类型
T
的对象的glvalue,或者- an expression is converted (either implicitly or explicitly) to type
T
, or表达式将(隐式或显式)转换为类型
T
,或者- an expression that is not a null pointer constant, and has type other than
void*
, is converted to the type pointer toT
or reference toT
using an implicit conversion, adynamic_cast
or astatic_cast
, or这不是一个空指针常量,并且具有比其他类型的表达式
void*
,被转换为类型指针T
或参考T
使用的隐式转换,一个dynamic_cast
或static_cast
,或- a class member access operator is applied to an expression of type
T
, or类成员访问运算符应用于类型
T
的表达式,或者- the
typeid
operator or thesizeof
operator is applied to an operand of typeT
, or将
typeid
运算符或sizeof
运算符应用于类型T
的操作数,或者- a function with a return type or argument type of type
T
is defined or called, or定义或调用了返回类型或参数类型为
T
的函数,或者- a class with a base class of type
T
is defined, or定义了具有
T
类型的基类的类,或者- an lvalue of type
T
is assigned to, or将类型
T
的左值分配给,或- the type
T
is the subject of analignof
expression, or类型
T
是alignof
表达式的主题,或者- an exception-declaration has type
T
, reference toT
, or pointer toT
.异常声明的类型为
T
,对T
引用或对T
指针。
The 6th bullet appears pertinent here, as we can see in §5.2.10/7 that a reinterpret_cast
between pointer types is defined in terms of static_cast
: 第六届子弹出现此相关的,因为我们可以在§5.2.10/ 7看到,
reinterpret_cast
指针类型之间的形式定义static_cast
:
An object pointer can be explicitly converted to an object pointer of a different type.
可以将对象指针显式转换为其他类型的对象指针。 When a prvalue
v
of type “pointer toT1
” is converted to the type “pointer to cvT2
”, the result isstatic_cast<cv T2*>(static_cast<cv void*>(v))
if bothT1
andT2
are standard-layout types and the alignment requirements ofT2
are no stricter than those ofT1
, or if either type isvoid
.当将“指向
T1
指针”的prvaluev
转换为“指向T2
指针”时,如果T1
和T2
都是标准的,则结果为static_cast<cv T2*>(static_cast<cv void*>(v))
-layout类型和的对准要求T2
是不严格的比的T1
,或者如果任一类型是void
。 Converting a prvalue of type “pointer toT1
” to the type “pointer toT2
” (whereT1
andT2
are object types and where the alignment requirements ofT2
are no stricter than those ofT1
) and back to its original type yields the original pointer value.转换类型的prvalue“指针
T1
”的类型“指针T2
”(其中T1
和T2
是对象类型,并且其中的对准要求T2
是不严格的比的T1
),并返回到其原始类型产生的原始指针值。 The result of any other such pointer conversion is unspecified.未指定任何其他此类指针转换的结果。
But because reinterpret_cast
static_cast
s to void*
first, then to the real resulting pointer type, that 6th bullet doesn't apply. 但是因为
reinterpret_cast
static_cast
s首先设置为void*
, 然后再设置为实际的指针类型,所以第6个项目符号不适用。
So, so far you're still in legal territory, despite T
being an incomplete type. 因此,到目前为止,尽管
T
是不完整的类型,但您仍处于合法范围内。 However, if it turns out that T
is not a standard-layout type or has stricter alignment requirements than int
, then the last sentence in §5.2.10/7 holds true and you're invoking UB. 但是,如果事实证明
T
不是标准布局类型或比int
更严格的对齐要求,则第5.2.10 / 7节中的最后一句话成立,您正在调用UB。
适用于您的情况的第5.2.10(7)节(根据ISO / IEC14882:1998(E),以及2011 FDIS中的规定)。
I'm not sure what you perceive as being allowed. 我不确定您认为允许什么。 There is a guarantee that you can
reinterpret_cast
from one pointer type to a sufficiently big other pointer type and back to the original type again and will be the original pointer. 可以保证您可以从一个指针类型
reinterpret_cast
到足够大的其他指针类型,然后再次返回到原始类型,并将成为原始指针。 The specification for this is in 5.2.10 [expr.reinterpret.cast]. 规范在5.2.10 [expr.reinterpret.cast]中。 That is, the following is guaranteed to work:
即,保证以下工作:
T* ptr = ...;
S* sptr = reinterpret_cast<S*>(ptr);
T* tptr = reinterpret_cast<T*>(sptr);
assert(ptr == tptr);
We had an out of session discussion earlier this week on this topic: if the Death Station 9000 implementation (which would be a conforming implementation of C++ but also tries to break user code wherever it is allowed to do so) XORs the bit pattern of the pointer with a bit pattern randomly chosen at the beginning of the program execution, would this be a permissible implementation if the types involved in the reinterpret_cast<T>(x)
are not involving char
. 我们在本周早些时候就该主题进行了闭门讨论:如果Death Station 9000实现(这是C ++的一致实现,但也尝试在允许这样做的地方打破用户代码),XOR会使用如果指针在程序执行开始时具有随机选择的位模式,则如果
reinterpret_cast<T>(x)
中涉及的类型不涉及char
,则这将是允许的实现。 The consensus was that this would be OK. 一致认为这是可以的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.