繁体   English   中英

C ++标准在哪里允许指向未定义类型的指针?

[英]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))如果两个T1T2是标准-layout类型(3.9)和T2的对齐要求并不比T1严格,或者如果任一类型都是void 转换类型的prvalue“指针T1 ”的类型“指针T2 ”(其中T1T2是对象类型,并且其中的对准要求T2是不严格的比的T1 ),并返回到其原始类型产生的原始指针值。 未指定任何其他此类指针转换的结果。

严格的别名规则禁止通过无关类型访问对象。 参见https://stackoverflow.com/a/7005988/103167

在第5.4节中找到了与您的问题有些相关的另一条规则:

使用强制转换表示法的强制转换操作数可以是“指向不完整类类型的指针”类型的prvalue。 使用 static_cast符号的static_cast目标类型可以是“指向不完整类类型的指针”如果操作数和目标类型都是类类型,并且一个或两个都不完整,则不确定是否使用static_castreinterpret_cast解释,甚至如果两个类之间存在继承关系。

您正在执行的操作可能是合法的,但这取决于class T的实际定义,因此根据您显示的代码我们不确定。

从C ++ 11§3.9.2/ 3开始:

尽管可以使用不完整类型的指针进行限制,但仍可以使用它们。

这些限制在§3.2/ 4中列出:

如果满足以下条件,则类类型T必须是完整的:

  • 定义了类型T的对象,或
  • 声明了类型T的非静态类数据成员,或者
  • Tnew-expression中用作对象类型或数组元素类型,或者
  • 左值到右值的转换应用于引用类型T的对象的glvalue,或者
  • 表达式将(隐式或显式)转换为类型T ,或者
  • 这不是一个空指针常量,并且具有比其他类型的表达式void* ,被转换为类型指针T或参考T使用的隐式转换,一个dynamic_caststatic_cast ,或
  • 类成员访问运算符应用于类型T的表达式,或者
  • typeid运算符或sizeof运算符应用于类型T的操作数,或者
  • 定义或调用了返回类型或参数类型为T的函数,或者
  • 定义了具有T类型的基类的类,或者
  • 将类型T的左值分配给,或
  • 类型Talignof表达式的主题,或者
  • 异常声明的类型为T ,对T引用或对T指针。

第六届子弹出现此相关的,因为我们可以在§5.2.10/ 7看到, reinterpret_cast指针类型之间的形式定义static_cast

可以将对象指针显式转换为其他类型的对象指针。 当将“指向T1指针”的prvalue v转换为“指向T2指针”时,如果T1T2都是标准的,则结果为static_cast<cv T2*>(static_cast<cv void*>(v)) -layout类型和的对准要求T2是不严格的比的T1 ,或者如果任一类型是void 转换类型的prvalue“指针T1 ”的类型“指针T2 ”(其中T1T2是对象类型,并且其中的对准要求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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM